Blockchain / Global / Address
Contract
0xbd8e690465E84e97075a89Fb30c64D5C44e04ad5
- Balance
- 0 SOMI
- Transactions sent
- 1
- Type
- Contract · 8,916 bytes of code
CrossChainRouter Verified
- Compiler
- solc 0.8.33+commit.64118f21
- Language
- Solidity
- Optimization
- Yes, 777777 runs
- EVM version
- prague
- License
- —
- Verified
- 2026-10-12
src/BrandedStablecoin/CrossChainRouter.sol
and 11 more files
Solidity
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.21;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ========================= CrossChainRouter =========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance
import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { IBrandedCustodian } from "src/BrandedStablecoin/interfaces/IBrandedCustodian.sol";
import { IGDollar } from "src/BrandedStablecoin/interfaces/IGDollar.sol";
import { IFrxUSD } from "src/interfaces/IFrxUSD.sol";
import { IRemoteHopV2 } from "src/BrandedStablecoin/interfaces/IRemoteHopV2.sol";
import { ILZSend } from "src/BrandedStablecoin/interfaces/ILzSend.sol";
/**
* @title CrossChainRouter
* @notice Implementation contract to be proxied. Intended to allow for branded stablecoins
* to be moved across supported EVM chains using the frax L0 mesh
*/
contract CrossChainRouter is AccessControl, ILZSend {
bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE");
uint128 public constant GLOBAL_COMPOSE_GAS = 500_000;
uint128 public constant SOMNIA_COMPOSE_GAS = 3_500_000;
bool public wasInitialized = true;
IBrandedCustodian public custodian;
IGDollar public coin;
IFrxUSD public frxusd;
address public oftLocal;
IRemoteHopV2 public remoteHopV2;
mapping(uint32 => bytes32) public eidToNonDeterministicAddress;
bool public isolatedBackingEnabled;
/**
* @notice Initialization function called w/n `FraxBrandedStablecoinFactory._deployBrandedTokenChained`
* @param _owner The address given the default admin role
* @param _custodianAddress The address of the brandedStablecoin custodian contract
* @param _coin The address of the brandedStablecoin proxy
* @param _localFrxUSD The local frxUSD OFT contract | either the OFT token or the lockbox
* @param _localRemoteHop The address of the RemoteHopV2 contract
*/
function initialize(
address _owner,
address _custodianAddress,
address _coin,
address _localFrxUSD,
address _localRemoteHop,
bool _isolatedBackingEnabled
) external {
if (wasInitialized) revert AlreadyInitialized();
_grantRole(DEFAULT_ADMIN_ROLE, _owner);
_grantRole(RELAYER_ROLE, _owner);
coin = IGDollar(_coin);
custodian = IBrandedCustodian(_custodianAddress);
if (block.chainid == 252) {
frxusd = IFrxUSD(0xFc00000000000000000000000000000000000001);
oftLocal = _localFrxUSD;
} else if (block.chainid == 1) {
frxusd = IFrxUSD(0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29);
oftLocal = _localFrxUSD;
} else {
frxusd = IFrxUSD(_localFrxUSD);
oftLocal = _localFrxUSD;
}
remoteHopV2 = IRemoteHopV2(payable(_localRemoteHop));
isolatedBackingEnabled = _isolatedBackingEnabled;
wasInitialized = true;
}
/**
* @notice External function used to coordinate the cross chain transfer of branded Stablecoin
* @param dstEid The EID corresponding to the chain that we want to send the stablecoin to
* @param recipient The evm address of the recipient on the dst chain
* @param amount The amount of the stablecoin that we want to send cross chain
*/
function send(uint32 dstEid, address recipient, uint256 amount) public payable {
bytes32 router = bytes32(uint(uint160(address(this))));
if (eidToNonDeterministicAddress[dstEid] != bytes32(0)) router = eidToNonDeterministicAddress[dstEid];
amount = (amount / 1e12) * 1e12; // Remove lzDust
coin.transferFrom(msg.sender, address(this), amount);
coin.approve(address(custodian), amount);
uint out = custodian.redeem(amount, address(this), address(this));
frxusd.approve(address(remoteHopV2), amount);
remoteHopV2.sendOFT{ value: msg.value }(
oftLocal,
dstEid,
router,
out,
dstEid == 30380 ? SOMNIA_COMPOSE_GAS : GLOBAL_COMPOSE_GAS,
abi.encode(recipient)
);
_refundExcess();
}
/**
* @notice External function used to facilitate the minting and sending of a branded stablecoin
* via the receipt of frxUSD
* @param dstEid The EID of the destination chain
* @param recipient The recipient on the destination chain
* @param amount The amount of frxUSD that we want to mint and send to the recipient
*/
function mintAndSend(uint32 dstEid, address recipient, uint256 amount) external payable returns (uint256 out) {
if (isolatedBackingEnabled) revert IsolatedBackingEnabled();
bytes32 router = bytes32(uint(uint160(address(this))));
if (eidToNonDeterministicAddress[dstEid] != bytes32(0)) router = eidToNonDeterministicAddress[dstEid];
amount = (amount / 1e12) * 1e12; // Remove lzDust
frxusd.transferFrom(msg.sender, address(this), amount);
frxusd.approve(address(remoteHopV2), amount);
out = amount;
remoteHopV2.sendOFT{ value: msg.value }(
oftLocal,
dstEid,
router,
out,
dstEid == 30380 ? SOMNIA_COMPOSE_GAS : GLOBAL_COMPOSE_GAS,
abi.encode(recipient)
);
_refundExcess();
}
/**
* @notice Internal helper function to refund any excess msg.value sent
*/
function _refundExcess() internal {
uint256 balance = address(this).balance;
if (balance > 0) {
(bool success, ) = msg.sender.call{ value: balance }("");
if (!success) revert RefundFailed();
}
}
/**
* @notice Helper function to calculate the amount of gas to send along with calls
* to `address(this).send(...)`
* @param dstEid The EID corresponding to the chain we want to send the token to
* @param recipient The evm address to send the tokens on the dst chain to
* @param amount The amount of tokens we want to send cross chain
*/
function quote(uint32 dstEid, address recipient, uint256 amount) public view returns (uint256) {
bytes32 router = bytes32(uint(uint160(address(this))));
if (eidToNonDeterministicAddress[dstEid] != bytes32(0)) router = eidToNonDeterministicAddress[dstEid];
uint fee = remoteHopV2.quote({
_oft: oftLocal,
_dstEid: dstEid,
_to: router,
_amountLD: (1e12 * (amount / 1e12)),
_composeGas: dstEid == 30380 ? SOMNIA_COMPOSE_GAS : GLOBAL_COMPOSE_GAS,
_composeMsg: abi.encode(recipient)
});
return (fee);
}
/**
* @notice Hook to be called by the remote hop on receiving a message passed
* @param oft The oft token corresponding to the msg being passed
* @param _amount The amount of oft token we
* @param data The data being passed through
* @dev Function call assumes frxUSD has been previously transfered to this contract
*/
function hopCompose(uint32 srcEid, bytes32 sender, address oft, uint256 _amount, bytes memory data) external {
if (msg.sender != address(remoteHopV2)) revert InvalidSender();
if (oft != oftLocal) revert InvalidOFT();
if (isolatedBackingEnabled) {
bytes32 router = eidToNonDeterministicAddress[srcEid];
if (router == bytes32(0)) router = bytes32(uint(uint160(address(this))));
if (sender != router) revert NotFromRouter();
}
(address recipient) = abi.decode(data, (address));
frxusd.approve(address(custodian), _amount);
custodian.deposit(_amount, recipient);
}
/**
* @notice Function to be implemented for non-determinist address deployment
* @param eid The eid for which we want to use a different router
* @param value The value we want to have the `recipient` field be equal to on the sendParams
*/
function setNonDeterministicRouterAddress(uint32 eid, bytes32 value) external onlyRole(RELAYER_ROLE) {
eidToNonDeterministicAddress[eid] = value;
emit NonDeterministicAddressSet(eid, value);
}
/**
* @notice Function for setting the remoteHopV2 address post deployment
* @param _updatedAddress The address of the updated hop contract
*/
function setHopV2Address(address _updatedAddress) external onlyRole(DEFAULT_ADMIN_ROLE) {
emit HopAddressUpdated(address(remoteHopV2), _updatedAddress);
remoteHopV2 = IRemoteHopV2(payable(_updatedAddress));
}
/**
* @notice Extension of LZ Send interface
* @param _sendParam Lz `_sendParam` tuple
* @param _payInLzToken whether to pay in LZ tokens | cannot be true
*/
function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory) {
if (_payInLzToken) revert MustPayNative();
if (bytes12(_sendParam.to) != bytes12(0)) revert MustBeEvmAddress();
if (_sendParam.composeMsg.length != 0) revert NotSupported();
if (_sendParam.oftCmd.length != 0) revert NotSupported();
uint amount = (_sendParam.amountLD / 1e12) * 1e12;
if (amount < _sendParam.minAmountLD) revert SlippageExceeded(amount, _sendParam.minAmountLD);
return
MessagingFee({
nativeFee: quote({
dstEid: _sendParam.dstEid,
recipient: address(uint160(uint(_sendParam.to))),
amount: amount
}),
lzTokenFee: 0
});
}
/**
* @notice Extension of LZ send interface
* @param _sendParam Lz `SendParam` tuple
* @param _fee Lz `MessagingFee` tuple
* @param _refundAddress Address for gas refund | must be caller
* @return MessagingReceipt - Place Holder variable for ABI conformity
* @return OFTReceipt - Place Holder variable for ABI conformity
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory, OFTReceipt memory) {
if (_fee.lzTokenFee != 0) revert MustPayNative();
if (_refundAddress != msg.sender) revert RefundMustBeSelf();
if (bytes12(_sendParam.to) != bytes12(0)) revert MustBeEvmAddress();
if (_sendParam.composeMsg.length != 0) revert NotSupported();
if (_sendParam.oftCmd.length != 0) revert NotSupported();
uint amount = (_sendParam.amountLD / 1e12) * 1e12;
if (amount < _sendParam.minAmountLD) revert SlippageExceeded(amount, _sendParam.minAmountLD);
send({ dstEid: _sendParam.dstEid, recipient: address(uint160(uint(_sendParam.to))), amount: _sendParam.amountLD });
MessagingReceipt memory receipt = MessagingReceipt({ guid: bytes32(0), nonce: 0, fee: _fee });
OFTReceipt memory oftReceipt = OFTReceipt({ amountSentLD: amount, amountReceivedLD: amount });
return (receipt, oftReceipt);
}
receive() external payable {}
/// Errors
error NotFromRouter();
error InvalidSender();
error InvalidOFT();
error AlreadyInitialized();
error RefundFailed();
error IsolatedBackingEnabled();
error MustPayNative();
error MustBeEvmAddress();
error RefundMustBeSelf();
error SlippageExceeded(uint256, uint256);
error NotSupported();
event HopAddressUpdated(address oldHopAddress, address newHopAddress);
event NonDeterministicAddressSet(uint32 eid, bytes32 router);
}
Other files
node_modules/@openzeppelin/contracts/access/AccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }node_modules/@openzeppelin/contracts/access/IAccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }node_modules/@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } }node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }src/BrandedStablecoin/interfaces/IBrandedCustodian.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IBrandedCustodian { error AmountTooHigh(); error ERC4626ExceededMaxDeposit(address receiver, uint256 assets, uint256 max); error ERC4626ExceededMaxMint(address receiver, uint256 shares, uint256 max); error ERC4626ExceededMaxRedeem(address owner, uint256 shares, uint256 max); error ERC4626ExceededMaxWithdraw(address owner, uint256 assets, uint256 max); error InitializeFailed(); error MintCapExceeded(address receiver, uint256 shares, uint256 mintCap); error NotOperator(); error OwnableInvalidOwner(address owner); error OwnableUnauthorizedAccount(address account); error OwnerCannotInitToZeroAddress(); error ReentrancyGuardReentrantCall(); error SafeERC20FailedOperation(address token); error SlippageTooHigh(); error TokenOwnerShouldBeSender(); event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); event MinAmountAfterShuffleSet(uint256 oldValue, uint256 newValue); event MintCapSet(uint256 mintCap); event OperatorStatusSet(address operator, bool status); event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event RecoveredERC20(address token, uint256 amount); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); event custodianTknShuffledToRwa(uint256 custodianTknAmount, address targetRwa); function acceptOwnership() external; function asset() external view returns (address _custodianTkn); function balanceOf(address _addr) external view returns (uint256 _balance); function brandedCoinMinted() external view returns (uint256); function brandedStablecoin() external view returns (address); function brandedTknDecimals() external view returns (uint8); function convertToAssets(uint256 _shares) external view returns (uint256 _assets); function convertToShares(uint256 _assets) external view returns (uint256 _shares); function custodianTkn() external view returns (address); function custodianTknDecimals() external view returns (uint8); function deposit(uint256 _assetsIn, address _receiver) external returns (uint256 _sharesOut); function initialize( address _brandedCoin, address _owner, uint256 _mintCap, uint256 _mintFee, uint256 _redeemFee ) external; function isApprovedOperator(address) external view returns (bool); function maxDeposit(address _addr) external view returns (uint256 _maxAssetsIn); function maxMint(address _addr) external view returns (uint256 _maxSharesOut); function maxRedeem(address _owner) external view returns (uint256 _maxSharesIn); function maxWithdraw(address _owner) external view returns (uint256 _maxAssetsOut); function mdwrComboView() external view returns ( uint256 _maxAssetsDepositable, uint256 _maxSharesMintable, uint256 _maxAssetsWithdrawable, uint256 _maxSharesRedeemable ); function minAfterShuffle() external view returns (uint256); function mint(uint256 _sharesOut, address _receiver) external returns (uint256 _assetsIn); function mintCap() external view returns (uint256); function mintFee() external view returns (uint256); function owner() external view returns (address); function pendingOwner() external view returns (address); function previewDeposit(uint256 _assetsIn) external view returns (uint256 _sharesOut); function previewMint(uint256 _sharesOut) external view returns (uint256 _assetsIn); function previewRedeem(uint256 _sharesIn) external view returns (uint256 _assetsOut); function previewWithdraw(uint256 _assetsOut) external view returns (uint256 _sharesIn); function pricePerShare() external view returns (uint256 _pricePerShare); function recoverERC20(address _tokenAddress, uint256 _tokenAmount) external; function redeem(uint256 _sharesIn, address _receiver, address _owner) external returns (uint256 _assetsOut); function redeemFee() external view returns (uint256); function renounceOwnership() external; function setApprovedOperator(address _operator, bool _status) external; function setMinAfterShuffle(uint256 _minAfterShuffle) external; function setMintCap(uint256 _mintCap) external; function setMintRedeemFee(uint256 _mintFee, uint256 _redeemFee) external; function totalAssets() external view returns (uint256 _assets); function totalSupply() external view returns (uint256 _supply); function transferOwnership(address newOwner) external; function wasInitialized() external view returns (bool); function withdraw(uint256 _assetsOut, address _receiver, address _owner) external returns (uint256 _sharesIn); }src/BrandedStablecoin/interfaces/IGDollar.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IGDollar { error AccessControlBadConfirmation(); error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); error ERC20InvalidApprover(address approver); error ERC20InvalidReceiver(address receiver); error ERC20InvalidSender(address sender); error ERC20InvalidSpender(address spender); error ExpiredAuthorization(); error InvalidAccountNonce(address account, uint256 currentNonce); error InvalidAuthorization(); error InvalidInitialization(); error InvalidPayee(address caller, address payee); error InvalidSignature(); error NotInitializing(); error UsedOrCanceledAuthorization(); event Approval(address indexed owner, address indexed spender, uint256 value); event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce); event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce); event EIP712DomainChanged(); event Initialized(uint64 version); event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); event Transfer(address indexed from, address indexed to, uint256 value); function DOMAIN_SEPARATOR() external view returns (bytes32); function DEFAULT_ADMIN_ROLE() external view returns (bytes32); function FACTORY_ROLE() external view returns (bytes32); function MINTER_ROLE() external view returns (bytes32); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function authorizationState(address authorizer, bytes32 nonce) external view returns (bool); function balanceOf(address account) external view returns (uint256); function burn(uint256 value) external; function burnFrom(address account, uint256 value) external; function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) external; function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) external; function decimals() external view returns (uint8); function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); function getRoleAdmin(bytes32 role) external view returns (bytes32); function grantRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns (bool); function initialize(string memory name, string memory symbol, address proxyAdminOwner) external; function mint(address account, uint256 value) external; function name() external view returns (string memory); function nonces(address owner) external view returns (uint256); function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external; function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function receiveWithAuthorization( address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, bytes memory signature ) external; function receiveWithAuthorization( address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s ) external; function renounceRole(bytes32 role, address callerConfirmation) external; function revokeRole(bytes32 role, address account) external; function supportsInterface(bytes4 interfaceId) external view returns (bool); function symbol() external view returns (string memory); function totalSupply() external view returns (uint256); function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function transferWithAuthorization( address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, bytes memory signature ) external; function transferWithAuthorization( address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s ) external; }src/BrandedStablecoin/interfaces/ILzSend.sol
// SPDX-License-Identifier: ISC pragma solidity ^0.8.19; interface ILZSend { struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; } struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } struct MessagingReceipt { bytes32 guid; uint64 nonce; MessagingFee fee; } struct OFTReceipt { uint256 amountSentLD; uint256 amountReceivedLD; } function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory); function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable returns (MessagingReceipt memory, OFTReceipt memory); }src/BrandedStablecoin/interfaces/IRemoteHopV2.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IRemoteHopV2 { struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } error HopPaused(); error InsufficientFee(); error InvalidOFT(); error InvalidOptionType(uint16 optionType); error InvalidSourceChain(); error InvalidSourceHop(); error NotEndpoint(); error OwnableInvalidOwner(address owner); error OwnableUnauthorizedAccount(address account); error RefundFailed(); error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); error SafeERC20FailedOperation(address token); error ZeroAmountSend(); event Hop(address oft, address indexed recipient, uint256 amount); event MessageHash(address oft, uint64 indexed nonce, bytes32 indexed fraxtalHop); event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event SendOFT(address oft, address indexed sender, uint32 indexed dstEid, bytes32 indexed to, uint256 amountLD); receive() external payable; function DVN() external view returns (address); function EID() external view returns (uint32); function ENDPOINT() external view returns (address); function EXECUTOR() external view returns (address); function TREASURY() external view returns (address); function acceptOwnership() external; function approvedOft(address) external view returns (bool); function executorOptions(uint32) external view returns (bytes memory); function fraxtalHop() external view returns (bytes32); function hopFee() external view returns (uint256); function lzCompose(address _oft, bytes32, bytes memory _message, address, bytes memory) external payable; function messageProcessed(bytes32) external view returns (bool); function numDVNs() external view returns (uint256); function owner() external view returns (address); function pause(bool _paused) external; function paused() external view returns (bool); function pendingOwner() external view returns (address); function quote( address _oft, uint32 _dstEid, bytes32 _to, uint256 _amountLD, uint128 _composeGas, bytes memory _composeMsg ) external view returns (uint256 fee); function quoteHop( uint32 _dstEid, uint128 _composeGas, bytes memory _composeMsg ) external view returns (uint256 finalFee); function recoverERC20(address tokenAddress, address recipient, uint256 tokenAmount) external; function recoverETH(address recipient, uint256 tokenAmount) external; function renounceOwnership() external; function sendOFT(address _oft, uint32 _dstEid, bytes32 _to, uint256 _amountLD) external payable; function sendOFT( address _oft, uint32 _dstEid, bytes32 _to, uint256 _amountLD, uint128 _composeGas, bytes memory _composeMsg ) external payable; function setExecutorOptions(uint32 eid, bytes memory _options) external; function setFraxtalHop(address _fraxtalHop) external; function setFraxtalHop(bytes32 _fraxtalHop) external; function setHopFee(uint256 _hopFee) external; function setMessageProcessed(address oft, uint64 nonce, bytes32 fraxtalHop) external; function setNumDVNs(uint256 _numDVNs) external; function toggleOFTApproval(address _oft, bool _approved) external; function transferOwnership(address newOwner) external; }src/interfaces/IFrxUSD.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IFrxUSD is IERC20 { error ArrayMisMatch(); error ECDSAInvalidSignature(); error ECDSAInvalidSignatureLength(uint256 length); error ECDSAInvalidSignatureS(bytes32 s); error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); error ERC20InvalidApprover(address approver); error ERC20InvalidReceiver(address receiver); error ERC20InvalidSender(address sender); error ERC20InvalidSpender(address spender); error ERC2612ExpiredSignature(uint256 deadline); error ERC2612InvalidSigner(address signer, address owner); error InvalidAccountNonce(address account, uint256 currentNonce); error InvalidShortString(); error IsFrozen(); error IsPaused(); error OwnableInvalidOwner(address owner); error OwnableUnauthorizedAccount(address account); error OwnerCannotInitToZeroAddress(); error StringTooLong(string str); event AccountFrozen(address account); event AccountThawed(address account); event Burn(address indexed account, uint256 amount); event EIP712DomainChanged(); event Mint(address indexed account, uint256 amount); event MinterAdded(address minter_address); event MinterRemoved(address minter_address); event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event Paused(); event TokenMinterBurned(address indexed from, address indexed to, uint256 amount); event TokenMinterMinted(address indexed from, address indexed to, uint256 amount); event Unpaused(); function DOMAIN_SEPARATOR() external view returns (bytes32); function acceptOwnership() external; function addMinter(address minter_address) external; function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function balanceOf(address account) external view returns (uint256); function burn(uint256 value) external; function burn(address _owner, uint256 _amount) external; function burnFrom(address account, uint256 value) external; function burnMany(address[] memory _owners, uint256[] memory _amounts) external; function decimals() external view returns (uint8); function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); function freeze(address _owner) external; function freezeMany(address[] memory _owners) external; function initialize(address _owner, string memory _name, string memory _symbol) external; function isFrozen(address) external view returns (bool); function isPaused() external view returns (bool); function minter_burn_from(address b_address, uint256 b_amount) external; function minter_mint(address m_address, uint256 m_amount) external; function minters(address) external view returns (bool); function minters_array(uint256) external view returns (address); function name() external view returns (string memory); function nonces(address owner) external view returns (uint256); function owner() external view returns (address); function pause() external; function pendingOwner() external view returns (address); function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function removeMinter(address minter_address) external; function renounceOwnership() external; function symbol() external view returns (string memory); function thaw(address _owner) external; function thawMany(address[] memory _owners) external; function totalSupply() external view returns (uint256); function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function transferOwnership(address newOwner) external; function unpause() external; }
ABI · 46 entries
json
[
{
"name": "AccessControlBadConfirmation",
"type": "error",
"inputs": []
},
{
"name": "AccessControlUnauthorizedAccount",
"type": "error",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "neededRole",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"name": "AlreadyInitialized",
"type": "error",
"inputs": []
},
{
"name": "InvalidOFT",
"type": "error",
"inputs": []
},
{
"name": "InvalidSender",
"type": "error",
"inputs": []
},
{
"name": "IsolatedBackingEnabled",
"type": "error",
"inputs": []
},
{
"name": "MustBeEvmAddress",
"type": "error",
"inputs": []
},
{
"name": "MustPayNative",
"type": "error",
"inputs": []
},
{
"name": "NotFromRouter",
"type": "error",
"inputs": []
},
{
"name": "NotSupported",
"type": "error",
"inputs": []
},
{
"name": "RefundFailed",
"type": "error",
"inputs": []
},
{
"name": "RefundMustBeSelf",
"type": "error",
"inputs": []
},
{
"name": "SlippageExceeded",
"type": "error",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "HopAddressUpdated",
"type": "event",
"inputs": [
{
"name": "oldHopAddress",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "newHopAddress",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "NonDeterministicAddressSet",
"type": "event",
"inputs": [
{
"name": "eid",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
},
{
"name": "router",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"name": "RoleAdminChanged",
"type": "event",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "previousAdminRole",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "newAdminRole",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"name": "RoleGranted",
"type": "event",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "RoleRevoked",
"type": "event",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "DEFAULT_ADMIN_ROLE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "GLOBAL_COMPOSE_GAS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "RELAYER_ROLE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "SOMNIA_COMPOSE_GAS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "coin",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IGDollar"
}
],
"stateMutability": "view"
},
{
"name": "custodian",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IBrandedCustodian"
}
],
"stateMutability": "view"
},
{
"name": "eidToNonDeterministicAddress",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "frxusd",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IFrxUSD"
}
],
"stateMutability": "view"
},
{
"name": "getRoleAdmin",
"type": "function",
"inputs": [
{
"name": "role",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "grantRole",
"type": "function",
"inputs": [
{
"name": "role",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "hasRole",
"type": "function",
"inputs": [
{
"name": "role",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "hopCompose",
"type": "function",
"inputs": [
{
"name": "srcEid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "sender",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "oft",
"type": "address",
"internalType": "address"
},
{
"name": "_amount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "initialize",
"type": "function",
"inputs": [
{
"name": "_owner",
"type": "address",
"internalType": "address"
},
{
"name": "_custodianAddress",
"type": "address",
"internalType": "address"
},
{
"name": "_coin",
"type": "address",
"internalType": "address"
},
{
"name": "_localFrxUSD",
"type": "address",
"internalType": "address"
},
{
"name": "_localRemoteHop",
"type": "address",
"internalType": "address"
},
{
"name": "_isolatedBackingEnabled",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "isolatedBackingEnabled",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "mintAndSend",
"type": "function",
"inputs": [
{
"name": "dstEid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "out",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "payable"
},
{
"name": "oftLocal",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "quote",
"type": "function",
"inputs": [
{
"name": "dstEid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "quoteSend",
"type": "function",
"inputs": [
{
"name": "_sendParam",
"type": "tuple",
"components": [
{
"name": "dstEid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "to",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "amountLD",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "minAmountLD",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "extraOptions",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "composeMsg",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "oftCmd",
"type": "bytes",
"internalType": "bytes"
}
],
"internalType": "struct ILZSend.SendParam"
},
{
"name": "_payInLzToken",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "nativeFee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "lzTokenFee",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct ILZSend.MessagingFee"
}
],
"stateMutability": "view"
},
{
"name": "remoteHopV2",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IRemoteHopV2"
}
],
"stateMutability": "view"
},
{
"name": "renounceRole",
"type": "function",
"inputs": [
{
"name": "role",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "callerConfirmation",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "revokeRole",
"type": "function",
"inputs": [
{
"name": "role",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "send",
"type": "function",
"inputs": [
{
"name": "_sendParam",
"type": "tuple",
"components": [
{
"name": "dstEid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "to",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "amountLD",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "minAmountLD",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "extraOptions",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "composeMsg",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "oftCmd",
"type": "bytes",
"internalType": "bytes"
}
],
"internalType": "struct ILZSend.SendParam"
},
{
"name": "_fee",
"type": "tuple",
"components": [
{
"name": "nativeFee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "lzTokenFee",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct ILZSend.MessagingFee"
},
{
"name": "_refundAddress",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "guid",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "nonce",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "fee",
"type": "tuple",
"components": [
{
"name": "nativeFee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "lzTokenFee",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct ILZSend.MessagingFee"
}
],
"internalType": "struct ILZSend.MessagingReceipt"
},
{
"name": "",
"type": "tuple",
"components": [
{
"name": "amountSentLD",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amountReceivedLD",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct ILZSend.OFTReceipt"
}
],
"stateMutability": "payable"
},
{
"name": "send",
"type": "function",
"inputs": [
{
"name": "dstEid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "payable"
},
{
"name": "setHopV2Address",
"type": "function",
"inputs": [
{
"name": "_updatedAddress",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setNonDeterministicRouterAddress",
"type": "function",
"inputs": [
{
"name": "eid",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "value",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "supportsInterface",
"type": "function",
"inputs": [
{
"name": "interfaceId",
"type": "bytes4",
"internalType": "bytes4"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "wasInitialized",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "receive",
"stateMutability": "payable"
}
]