Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Send Payload To ... | 20634672 | 545 days ago | 0.00010873 ETH | ||||
| Send Message | 20634672 | 545 days ago | 0.00010873 ETH | ||||
| Send Payload To ... | 20634079 | 545 days ago | 0.00011103 ETH | ||||
| Send Message | 20634079 | 545 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20633484 | 545 days ago | 0.00011103 ETH | ||||
| Send Message | 20633484 | 545 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20632886 | 545 days ago | 0.00011103 ETH | ||||
| Send Message | 20632886 | 545 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20632291 | 545 days ago | 0.00011103 ETH | ||||
| Send Message | 20632291 | 545 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20631699 | 546 days ago | 0.00011103 ETH | ||||
| Send Message | 20631699 | 546 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20631104 | 546 days ago | 0.00011103 ETH | ||||
| Send Message | 20631104 | 546 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20630505 | 546 days ago | 0.00011103 ETH | ||||
| Send Message | 20630505 | 546 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20630307 | 546 days ago | 0.00011103 ETH | ||||
| Send Message | 20630307 | 546 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20629909 | 546 days ago | 0.00011103 ETH | ||||
| Send Message | 20629909 | 546 days ago | 0.00011103 ETH | ||||
| Send Payload To ... | 20629315 | 546 days ago | 0.00010867 ETH | ||||
| Send Message | 20629315 | 546 days ago | 0.00010867 ETH | ||||
| Send Payload To ... | 20628715 | 546 days ago | 0.00010867 ETH | ||||
| Send Message | 20628715 | 546 days ago | 0.00010867 ETH | ||||
| Send Payload To ... | 20628120 | 546 days ago | 0.00011234 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
WormholeHubConnector
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
import {IRootManager} from "../../interfaces/IRootManager.sol";
import {IWormholeReceiver} from "../../interfaces/ambs/wormhole/IWormholeReceiver.sol";
import {HubConnector, Connector} from "../HubConnector.sol";
import {BaseWormhole} from "./BaseWormhole.sol";
contract WormholeHubConnector is HubConnector, BaseWormhole, IWormholeReceiver {
// ============ Constructor ============
constructor(
uint32 _domain,
uint32 _mirrorDomain,
address _amb,
address _rootManager,
address _mirrorConnector,
uint256 _gasCap,
uint16 _mirrorWormholeChainId
)
HubConnector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector)
BaseWormhole(_gasCap, _mirrorWormholeChainId)
{}
// ============ Override Fns ============
function _verifySender(address _expected) internal view override returns (bool) {
return _verifySender(mirrorConnector, _expected);
}
// ============ Public fns ============
/**
* @notice This function is called to receive messages through the wormhole relayer module
* https://book.wormhole.com/technical/evm/relayer.html
* @dev This is defined here instead of the `BaseWormhole` to avoid storing AMB values twice.
*/
function receiveWormholeMessages(
bytes memory _payload,
bytes[] memory, // additionalVaas,
bytes32 _sourceAddress,
uint16 _sourceChain,
bytes32 _deliveryHash
) public payable override {
_wormholeSanityChecks(_sourceChain, AMB, _deliveryHash);
_processMessageFrom(_fromWormholeFormat(_sourceAddress), _payload);
}
// ============ Private fns ============
/**
* @dev Handles an incoming `outboundRoot`
*/
function _processMessageFrom(address _sender, bytes memory _data) internal override(BaseWormhole) {
// enforce this came from connector on l2
require(_verifySender(_sender), "!l2Connector");
// get the data (should be the outbound root)
require(_data.length == 32, "!length");
// set the outbound root for BSC domain
IRootManager(ROOT_MANAGER).aggregate(MIRROR_DOMAIN, bytes32(_data));
emit MessageProcessed(_data, msg.sender);
}
function _sendMessage(bytes memory _data, bytes memory _encodedData) internal override {
_sendMessage(AMB, mirrorConnector, _data, _encodedData);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {ProposedOwnable} from "../../shared/ProposedOwnable.sol";
import {IConnector} from "../interfaces/IConnector.sol";
/**
* @title Connector
* @author Connext Labs, Inc.
* @notice This contract has the messaging interface functions used by all connectors.
*
* @dev This contract stores information about mirror connectors, but can be used as a
* base for contracts that do not have a mirror (i.e. the connector handling messaging on
* mainnet). In this case, the `mirrorConnector` and `MIRROR_DOMAIN`
* will be empty
*
* @dev If ownership is renounced, this contract will be unable to update its `mirrorConnector`
* or `mirrorGas`
*/
abstract contract Connector is ProposedOwnable, IConnector {
// ========== Custom Errors ===========
error Connector__processMessage_notUsed();
// ============ Events ============
event NewConnector(
uint32 indexed domain,
uint32 indexed mirrorDomain,
address amb,
address rootManager,
address mirrorConnector
);
event MirrorConnectorUpdated(address previous, address current);
/**
* @notice Emitted when funds are withdrawn by the admin
* @dev See comments in `withdrawFunds`
* @param to The recipient of the funds
* @param amount The amount withdrawn
*/
event FundsWithdrawn(address indexed to, uint256 amount);
// ============ Public Storage ============
/**
* @notice The domain of this Messaging (i.e. Connector) contract.
*/
uint32 public immutable DOMAIN;
/**
* @notice Address of the AMB on this domain.
*/
address public immutable AMB;
/**
* @notice RootManager contract address.
*/
address public immutable ROOT_MANAGER;
/**
* @notice The domain of the corresponding messaging (i.e. Connector) contract.
*/
uint32 public immutable MIRROR_DOMAIN;
/**
* @notice Connector on L2 for L1 connectors, and vice versa.
*/
address public mirrorConnector;
// ============ Modifiers ============
/**
* @notice Errors if the msg.sender is not the registered AMB
*/
modifier onlyAMB() {
require(msg.sender == AMB, "!AMB");
_;
}
/**
* @notice Errors if the msg.sender is not the registered ROOT_MANAGER
*/
modifier onlyRootManager() {
// NOTE: RootManager will be zero address for spoke connectors.
// Only root manager can dispatch a message to spokes/L2s via the hub connector.
require(msg.sender == ROOT_MANAGER, "!rootManager");
_;
}
// ============ Constructor ============
/**
* @notice Creates a new HubConnector instance
* @dev The connectors are deployed such that there is one on each side of an AMB (i.e.
* for optimism, there is one connector on optimism and one connector on mainnet)
* @param _domain The domain this connector lives on
* @param _mirrorDomain The spoke domain
* @param _amb The address of the amb on the domain this connector lives on
* @param _rootManager The address of the RootManager on mainnet
* @param _mirrorConnector The address of the spoke connector
*/
constructor(
uint32 _domain,
uint32 _mirrorDomain,
address _amb,
address _rootManager,
address _mirrorConnector
) ProposedOwnable() {
// set the owner
_setOwner(msg.sender);
// sanity checks on values
require(_domain != 0, "empty domain");
require(_rootManager != address(0), "empty rootManager");
// see note at top of contract on why the mirror values are not sanity checked
// set immutables
DOMAIN = _domain;
AMB = _amb;
ROOT_MANAGER = _rootManager;
MIRROR_DOMAIN = _mirrorDomain;
// set mutables if defined
if (_mirrorConnector != address(0)) {
_setMirrorConnector(_mirrorConnector);
}
emit NewConnector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector);
}
// ============ Receivable ============
/**
* @notice Connectors may need to receive native asset to handle fees when sending a
* message
*/
receive() external payable {}
// ============ Admin Functions ============
/**
* @notice Sets the address of the l2Connector for this domain
*/
function setMirrorConnector(address _mirrorConnector) public onlyOwner {
_setMirrorConnector(_mirrorConnector);
}
/**
* @notice This function should be callable by owner, and send funds trapped on
* a connector to the provided recipient.
* @dev Withdraws the entire balance of the contract.
*
* @param _to The recipient of the funds withdrawn
*/
function withdrawFunds(address _to) public onlyOwner {
uint256 amount = address(this).balance;
Address.sendValue(payable(_to), amount);
emit FundsWithdrawn(_to, amount);
}
// ============ Public Functions ============
/**
* @notice Processes a message received by an AMB
* @dev This is called by AMBs to process messages originating from mirror connector
*/
function processMessage(bytes memory _data) external virtual onlyAMB {
_processMessage(_data);
emit MessageProcessed(_data, msg.sender);
}
/**
* @notice Checks the cross domain sender for a given address
*/
function verifySender(address _expected) external returns (bool) {
return _verifySender(_expected);
}
// ============ Virtual Functions ============
/**
* @notice This function is used by the Connext contract on the l2 domain to send a message to the
* l1 domain (i.e. called by Connext on optimism to send a message to mainnet with roots)
* @param _data The contents of the message
* @param _encodedData Data used to send the message; specific to connector
*/
function _sendMessage(bytes memory _data, bytes memory _encodedData) internal virtual;
/**
* @notice This function is used by the AMBs to handle incoming messages. Should store the latest
* root generated on the l2 domain.
*/
function _processMessage(
bytes memory /* _data */
) internal virtual {
// By default, reverts. This is to ensure the call path is not used unless this function is
// overridden by the inheriting class
revert Connector__processMessage_notUsed();
}
/**
* @notice Verify that the msg.sender is the correct AMB contract, and that the message's origin sender
* is the expected address.
* @dev Should be overridden by the implementing Connector contract.
*/
function _verifySender(address _expected) internal virtual returns (bool);
// ============ Private Functions ============
function _setMirrorConnector(address _mirrorConnector) internal virtual {
emit MirrorConnectorUpdated(mirrorConnector, _mirrorConnector);
mirrorConnector = _mirrorConnector;
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {ProposedOwnable} from "../../shared/ProposedOwnable.sol";
/**
* @notice This contract is used to enforce upper bounds on the amount of fees
* forwarded along. This caps the amount relayers could charge for the service
*/
abstract contract GasCap is ProposedOwnable {
// ============ Storage ============
/**
* @notice The gnosis amb requires destination gas to be specified on the origin.
* The gas used will be passed in by the relayer to allow for real-time estimates,
* but will be capped at the admin-set cap.
*/
uint256 public gasCap;
// ============ Events ============
/**
* @notice Emitted when admin updates the gas cap
* @param _previous The starting value
* @param _updated The final value
*/
event GasCapUpdated(uint256 _previous, uint256 _updated);
// ============ Constructor ============
constructor(uint256 _gasCap) {
_setGasCap(_gasCap);
}
// ============ Admin Fns ============
function setGasCap(uint256 _gasCap) public onlyOwner {
_setGasCap(_gasCap);
}
// ============ Internal Fns ============
/**
* @notice Used (by admin) to update the gas cap
* @param _gasCap The new value
*/
function _setGasCap(uint256 _gasCap) internal {
emit GasCapUpdated(gasCap, _gasCap);
gasCap = _gasCap;
}
/**
* @notice Used to get the gas to use. Will be the original value IFF it
* is less than the cap
* @param _gas The proposed gas value
*/
function _getGas(uint256 _gas) internal view returns (uint256) {
if (_gas > gasCap) {
_gas = gasCap;
}
return _gas;
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
import {Connector} from "./Connector.sol";
/**
* @title HubConnector
* @author Connext Labs, Inc.
* @notice This contract implements the messaging functions needed on the hub-side of a given AMB.
* The HubConnector has a limited set of functionality compared to the SpokeConnector, namely that
* it contains no logic to store or prove messages.
*
* @dev This contract should be deployed on the hub-side of an AMB (i.e. on L1), and contracts
* which extend this should implement the virtual functions defined in the BaseConnector class
*/
abstract contract HubConnector is Connector {
/**
* @notice Creates a new HubConnector instance
* @dev The connectors are deployed such that there is one on each side of an AMB (i.e.
* for optimism, there is one connector on optimism and one connector on mainnet)
* @param _domain The domain this connector lives on
* @param _mirrorDomain The spoke domain
* @param _amb The address of the amb on the domain this connector lives on
* @param _rootManager The address of the RootManager on mainnet
* @param _mirrorConnector The address of the spoke connector
*/
constructor(
uint32 _domain,
uint32 _mirrorDomain,
address _amb,
address _rootManager,
address _mirrorConnector
) Connector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector) {}
// ============ Public fns ============
/**
* @notice Sends a message over the amb
* @dev This is called by the root manager *only* on mainnet to propagate the aggregate root
*/
function sendMessage(bytes memory _data, bytes memory _encodedData) external payable onlyRootManager {
_sendMessage(_data, _encodedData);
emit MessageSent(_data, _encodedData, msg.sender);
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
import {IWormholeRelayer} from "../../interfaces/ambs/wormhole/IWormholeRelayer.sol";
import {GasCap} from "../GasCap.sol";
abstract contract BaseWormhole is GasCap {
// ============ Events ============
event RefundAddressUpdated(address indexed previous, address indexed updated);
// ============ Storage ============
/**
* @notice The wormhole id for the mirror network
*/
uint16 public immutable MIRROR_WORMHOLE_ID;
/**
* @notice The address on this chain any refunds from wormhole fees will be
* sent to
*/
address public refundAddress;
/**
* @notice Mapping of processed messages from wormhole.
* @dev Used for replay protection.
*/
mapping(bytes32 => bool) public processedWhMessages;
// ============ Constructor ============
constructor(uint256 _gasCap, uint16 _mirrorWormholeChainId) GasCap(_gasCap) {
MIRROR_WORMHOLE_ID = _mirrorWormholeChainId;
_setRefundAddress(msg.sender);
}
// ============ Admin fns ============
/**
* @notice Allows the owner to set a new address to collect excess wormhole fees.
* @param _updated The updated refund address
*/
function setRefundAddress(address _updated) public onlyOwner {
_setRefundAddress(_updated);
}
// ============ Public fns ============
/**
* @dev calculcate gas to call `receiveWormholeMessages` on target chain
* https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/relayer/deliveryProvider/DeliveryProvider.sol
*/
function quoteEVMDeliveryPrice(uint256 _gasLimit, address _amb) public view returns (uint256 _cost) {
// First Get the gas, if it is more than the cap use the cap
// And calculcate delievery price with gasCap
(_cost, ) = IWormholeRelayer(_amb).quoteEVMDeliveryPrice(MIRROR_WORMHOLE_ID, 0, _getGas(_gasLimit));
}
// ============ Private fns ============
function _setRefundAddress(address _updated) internal {
require(_updated != refundAddress, "!changed");
emit RefundAddressUpdated(refundAddress, _updated);
refundAddress = _updated;
}
/**
* @dev Asserts the sender of a cross domain message
*/
function _verifySender(address _mirrorConnector, address _expected) internal pure returns (bool) {
return _mirrorConnector == _expected;
}
// DO NOT override _processMessage, should revert from `Connector` class. All messages must use the _processMessageFrom function
/**
* @notice This function is called to handle incoming messages. Should store the latest
* root generated on the l2 domain.
*/
function _processMessageFrom(address _sender, bytes memory _data) internal virtual;
/**
* @notice Performs sanity checks specific to receiving wormhole messages.
* @dev Checks the sender is the AMB, the chain is the mirror, and replay.
*/
function _wormholeSanityChecks(uint16 _sourceChain, address _amb, bytes32 _deliveryHash) internal {
require(_sourceChain == MIRROR_WORMHOLE_ID, "!source chain");
require(msg.sender == _amb, "!relayer");
// Check that the VAA hasn't already been processed (replay protection)
require(!processedWhMessages[_deliveryHash], "already processed");
// Add the VAA to processed messages so it can't be replayed
// you can alternatively rely on the replay protection
// of something like transferWithPayload from the Token Bridge module
processedWhMessages[_deliveryHash] = true;
}
/**
* @dev send message via wormhole.
* https://book.wormhole.com/technical/evm/relayer.html#sending-messages
*/
function _sendMessage(
address _amb,
address _mirrorConnector,
bytes memory _data,
bytes memory _encodedData
) internal {
// Should always be sending a merkle root
require(_data.length == 32, "!data length");
// Should include gas limit info in specialized calldata
require(_encodedData.length == 32, "!encoded data length");
//calculate cost to deliver message
uint256 gasLimit = abi.decode(_encodedData, (uint256));
uint256 deliveryCost = quoteEVMDeliveryPrice(gasLimit, _amb);
require(deliveryCost == msg.value, "!msg.value");
// publish delivery request
IWormholeRelayer(_amb).sendPayloadToEvm{value: deliveryCost}(
MIRROR_WORMHOLE_ID,
_mirrorConnector,
_data,
0,
gasLimit,
MIRROR_WORMHOLE_ID, // refundChain
refundAddress // refundAddress
);
}
/**
* @notice Converts from wormhole 32 byte identifier format to evm address
*/
function _fromWormholeFormat(bytes32 _whFormatAddress) internal pure returns (address) {
require(uint256(_whFormatAddress) >> 160 == 0, "!evm address");
return address(uint160(uint256(_whFormatAddress)));
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
import {IProposedOwnable} from "../../shared/interfaces/IProposedOwnable.sol";
/**
* @notice This interface is what the Connext contract will send and receive messages through.
* The messaging layer should conform to this interface, and should be interchangeable (i.e.
* could be Nomad or a generic AMB under the hood).
*
* @dev This uses the nomad format to ensure nomad can be added in as it comes back online.
*
* Flow from transfer from polygon to optimism:
* 1. User calls `xcall` with destination specified
* 2. This will swap in to the bridge assets
* 3. The swapped assets will get burned
* 4. The Connext contract will call `dispatch` on the messaging contract to add the transfer
* to the root
* 5. [At some time interval] Relayers call `send` to send the current root from polygon to
* mainnet. This is done on all "spoke" domains.
* 6. [At some time interval] Relayers call `propagate` [better name] on mainnet, this generates a new merkle
* root from all of the AMBs
* - This function must be able to read root data from all AMBs and aggregate them into a single merkle
* tree root
* - Will send the mixed root from all chains back through the respective AMBs to all other chains
* 7. AMB will call `update` to update the latest root on the messaging contract on spoke domains
* 8. [At any point] Relayers can call `proveAndProcess` to prove inclusion of dispatched message, and call
* process on the `Connext` contract
* 9. Takes minted bridge tokens and credits the LP
*
* AMB requirements:
* - Access `msg.sender` both from mainnet -> spoke and vice versa
* - Ability to read *our root* from the AMB
*
* AMBs:
* - PoS bridge from polygon
* - arbitrum bridge
* - optimism bridge
* - gnosis chain
* - bsc (use multichain for messaging)
*/
interface IConnector is IProposedOwnable {
// ============ Events ============
/**
* @notice Emitted whenever a message is successfully sent over an AMB
* @param data The contents of the message
* @param encodedData Data used to send the message; specific to connector
* @param caller Who called the function (sent the message)
*/
event MessageSent(bytes data, bytes encodedData, address caller);
/**
* @notice Emitted whenever a message is successfully received over an AMB
* @param data The contents of the message
* @param caller Who called the function
*/
event MessageProcessed(bytes data, address caller);
// ============ Public fns ============
function processMessage(bytes memory _data) external;
function verifySender(address _expected) external returns (bool);
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;
interface IRootManager {
/**
* @notice This is called by relayers to generate + send the mixed root from mainnet via AMB to
* spoke domains.
* @dev This must read information for the root from the registered AMBs.
*/
function propagate(
address[] calldata _connectors,
uint256[] calldata _fees,
bytes[] memory _encodedData
) external payable;
/**
* @notice Called by the connectors for various domains on the hub to aggregate their latest
* inbound root.
* @dev This must read information for the root from the registered AMBs
*/
function aggregate(uint32 _domain, bytes32 _outbound) external;
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
/**
* @notice Interface for a contract which can receive Wormhole messages.
*/
interface IWormholeReceiver {
/**
* @notice When a `send` is performed with this contract as the target, this function will be
* invoked by the WormholeRelayer contract
*
* NOTE: This function should be restricted such that only the Wormhole Relayer contract can call it.
*
* We also recommend that this function:
* - Stores all received `deliveryHash`s in a mapping `(bytes32 => bool)`, and
* on every call, checks that deliveryHash has not already been stored in the
* map (This is to prevent other users maliciously trying to relay the same message)
* - Checks that `sourceChain` and `sourceAddress` are indeed who
* you expect to have requested the calling of `send` or `forward` on the source chain
*
* The invocation of this function corresponding to the `send` request will have msg.value equal
* to the receiverValue specified in the send request.
*
* If the invocation of this function reverts or exceeds the gas limit
* specified by the send requester, this delivery will result in a `ReceiverFailure`.
*
* @param payload - an arbitrary message which was included in the delivery by the
* requester.
* @param additionalVaas - Additional VAAs which were requested to be included in this delivery.
* They are guaranteed to all be included and in the same order as was specified in the
* delivery request.
* @param sourceAddress - the (wormhole format) address on the sending chain which requested
* this delivery.
* @param sourceChain - the wormhole chain ID where this delivery was requested.
* @param deliveryHash - the VAA hash of the deliveryVAA.
*
* NOTE: These signedVaas are NOT verified by the Wormhole core contract prior to being provided
* to this call. Always make sure `parseAndVerify()` is called on the Wormhole core contract
* before trusting the content of a raw VAA, otherwise the VAA may be invalid or malicious.
*/
function receiveWormholeMessages(
bytes memory payload,
bytes[] memory additionalVaas,
bytes32 sourceAddress,
uint16 sourceChain,
bytes32 deliveryHash
) external payable;
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
/**
* @title WormholeRelayer
* @author
* @notice This project allows developers to build cross-chain applications powered by Wormhole without needing to
* write and run their own relaying infrastructure
*
* We implement the IWormholeRelayer interface that allows users to request a delivery provider to relay a payload (and/or additional VAAs)
* to a chain and address of their choice.
*/
/**
* @notice VaaKey identifies a wormhole message
*
* @custom:member chainId Wormhole chain ID of the chain where this VAA was emitted from
* @custom:member emitterAddress Address of the emitter of the VAA, in Wormhole bytes32 format
* @custom:member sequence Sequence number of the VAA
*/
struct VaaKey {
uint16 chainId;
bytes32 emitterAddress;
uint64 sequence;
}
interface IWormholeRelayerBase {
event SendEvent(uint64 indexed sequence, uint256 deliveryQuote, uint256 paymentForExtraReceiverValue);
function getRegisteredWormholeRelayerContract(uint16 chainId) external view returns (bytes32);
}
/**
* @title IWormholeRelayerSend
* @notice The interface to request deliveries
*/
interface IWormholeRelayerSend is IWormholeRelayerBase {
/**
* @notice Publishes an instruction for the default delivery provider
* to relay a payload to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and `msg.value` equal to `receiverValue`
*
* `targetAddress` must implement the IWormholeReceiver interface
*
* This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`
*
* Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendPayloadToEvm` function
* with `refundChain` and `refundAddress` as parameters
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver)
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`.
* @return sequence sequence number of published VAA containing delivery instructions
*/
function sendPayloadToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit
) external payable returns (uint64 sequence);
/**
* @notice Publishes an instruction for the default delivery provider
* to relay a payload to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and `msg.value` equal to `receiverValue`
*
* Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`
* `targetAddress` must implement the IWormholeReceiver interface
*
* This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver)
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the
* `targetChainRefundPerGasUnused` rate quoted by the delivery provider
* @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format
* @param refundAddress The address on `refundChain` to deliver any refund to
* @return sequence sequence number of published VAA containing delivery instructions
*/
function sendPayloadToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit,
uint16 refundChain,
address refundAddress
) external payable returns (uint64 sequence);
/**
* @notice Publishes an instruction for the default delivery provider
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and `msg.value` equal to `receiverValue`
*
* `targetAddress` must implement the IWormholeReceiver interface
*
* This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`
*
* Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendVaasToEvm` function
* with `refundChain` and `refundAddress` as parameters
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver)
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`.
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
* @return sequence sequence number of published VAA containing delivery instructions
*/
function sendVaasToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit,
VaaKey[] memory vaaKeys
) external payable returns (uint64 sequence);
/**
* @notice Publishes an instruction for the default delivery provider
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and `msg.value` equal to `receiverValue`
*
* Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`
* `targetAddress` must implement the IWormholeReceiver interface
*
* This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver)
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the
* `targetChainRefundPerGasUnused` rate quoted by the delivery provider
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
* @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format
* @param refundAddress The address on `refundChain` to deliver any refund to
* @return sequence sequence number of published VAA containing delivery instructions
*/
function sendVaasToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit,
VaaKey[] memory vaaKeys,
uint16 refundChain,
address refundAddress
) external payable returns (uint64 sequence);
/**
* @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress`
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and `msg.value` equal to
* receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.
*
* Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`
* `targetAddress` must implement the IWormholeReceiver interface
*
* This function must be called with `msg.value` equal to
* quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit, deliveryProviderAddress) + paymentForExtraReceiverValue
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver)
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue
* (in addition to the `receiverValue` specified)
* @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the
* `targetChainRefundPerGasUnused` rate quoted by the delivery provider
* @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format
* @param refundAddress The address on `refundChain` to deliver any refund to
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
* @param consistencyLevel Consistency level with which to publish the delivery instructions - see
* https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels
* @return sequence sequence number of published VAA containing delivery instructions
*/
function sendToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 paymentForExtraReceiverValue,
uint256 gasLimit,
uint16 refundChain,
address refundAddress,
address deliveryProviderAddress,
VaaKey[] memory vaaKeys,
uint8 consistencyLevel
) external payable returns (uint64 sequence);
/**
* @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress`
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with `msg.value` equal to
* receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.
*
* Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`
* `targetAddress` must implement the IWormholeReceiver interface
*
* This function must be called with `msg.value` equal to
* quoteDeliveryPrice(targetChain, receiverValue, encodedExecutionParameters, deliveryProviderAddress) + paymentForExtraReceiverValue
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue
* (in addition to the `receiverValue` specified)
* @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing
* e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`
* @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format
* @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
* @param consistencyLevel Consistency level with which to publish the delivery instructions - see
* https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels
* @return sequence sequence number of published VAA containing delivery instructions
*/
function send(
uint16 targetChain,
bytes32 targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 paymentForExtraReceiverValue,
bytes memory encodedExecutionParameters,
uint16 refundChain,
bytes32 refundAddress,
address deliveryProviderAddress,
VaaKey[] memory vaaKeys,
uint8 consistencyLevel
) external payable returns (uint64 sequence);
/**
* @notice Performs the same function as a `send`, except:
* 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`)
* 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery)
* 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number)
*
* The refund from the delivery currently in progress will not be sent to the user; it will instead
* be paid to the delivery provider to perform the instruction specified here
*
* Publishes an instruction for the same delivery provider (or default, if the same one doesn't support the new target chain)
* to relay a payload to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and with `msg.value` equal to `receiverValue`
*
* The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`):
* (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f]
* >= sum_f [quoteEVMDeliveryPrice(targetChain_f, receiverValue_f, gasLimit_f)]
*
* The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested
*
* Any refunds (from leftover gas) from this forward will be paid to the same refundChain and refundAddress specified for the current delivery.
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`.
*/
function forwardPayloadToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit
) external payable;
/**
* @notice Performs the same function as a `send`, except:
* 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`)
* 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery)
* 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number)
*
* The refund from the delivery currently in progress will not be sent to the user; it will instead
* be paid to the delivery provider to perform the instruction specified here
*
* Publishes an instruction for the same delivery provider (or default, if the same one doesn't support the new target chain)
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and with `msg.value` equal to `receiverValue`
*
* The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`):
* (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f]
* >= sum_f [quoteEVMDeliveryPrice(targetChain_f, receiverValue_f, gasLimit_f)]
*
* The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested
*
* Any refunds (from leftover gas) from this forward will be paid to the same refundChain and refundAddress specified for the current delivery.
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`.
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
*/
function forwardVaasToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit,
VaaKey[] memory vaaKeys
) external payable;
/**
* @notice Performs the same function as a `send`, except:
* 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`)
* 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery)
* 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number)
*
* The refund from the delivery currently in progress will not be sent to the user; it will instead
* be paid to the delivery provider to perform the instruction specified here
*
* Publishes an instruction for the delivery provider at `deliveryProviderAddress`
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with gas limit `gasLimit` and with `msg.value` equal to
* receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.
*
* Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`
* `targetAddress` must implement the IWormholeReceiver interface
*
* The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`):
* (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f]
* >= sum_f [quoteEVMDeliveryPrice(targetChain_f, receiverValue_f, gasLimit_f, deliveryProviderAddress_f) + paymentForExtraReceiverValue_f]
*
* The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue
* (in addition to the `receiverValue` specified)
* @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the
* `targetChainRefundPerGasUnused` rate quoted by the delivery provider
* @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format
* @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
* @param consistencyLevel Consistency level with which to publish the delivery instructions - see
* https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels
*/
function forwardToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 paymentForExtraReceiverValue,
uint256 gasLimit,
uint16 refundChain,
address refundAddress,
address deliveryProviderAddress,
VaaKey[] memory vaaKeys,
uint8 consistencyLevel
) external payable;
/**
* @notice Performs the same function as a `send`, except:
* 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`)
* 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery)
* 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number)
*
* The refund from the delivery currently in progress will not be sent to the user; it will instead
* be paid to the delivery provider to perform the instruction specified here
*
* Publishes an instruction for the delivery provider at `deliveryProviderAddress`
* to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`
* with `msg.value` equal to
* receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.
*
* Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`
* `targetAddress` must implement the IWormholeReceiver interface
*
* The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`):
* (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f]
* >= sum_f [quoteDeliveryPrice(targetChain_f, receiverValue_f, encodedExecutionParameters_f, deliveryProviderAddress_f) + paymentForExtraReceiverValue_f]
*
* The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested
*
* @param targetChain in Wormhole Chain ID format
* @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format
* @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue
* (in addition to the `receiverValue` specified)
* @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing
* e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`
* @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format
* @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`
* @param consistencyLevel Consistency level with which to publish the delivery instructions - see
* https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels
*/
function forward(
uint16 targetChain,
bytes32 targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 paymentForExtraReceiverValue,
bytes memory encodedExecutionParameters,
uint16 refundChain,
bytes32 refundAddress,
address deliveryProviderAddress,
VaaKey[] memory vaaKeys,
uint8 consistencyLevel
) external payable;
/**
* @notice Requests a previously published delivery instruction to be redelivered
* (e.g. with a different delivery provider)
*
* This function must be called with `msg.value` equal to
* quoteEVMDeliveryPrice(targetChain, newReceiverValue, newGasLimit, newDeliveryProviderAddress)
*
* @param deliveryVaaKey VaaKey identifying the wormhole message containing the
* previously published delivery instructions
* @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions
* @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param newGasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the
* `targetChainRefundPerGasUnused` rate quoted by the delivery provider, to the refund chain and address specified in the original request
* @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @return sequence sequence number of published VAA containing redelivery instructions
*/
function resendToEvm(
VaaKey memory deliveryVaaKey,
uint16 targetChain,
uint256 newReceiverValue,
uint256 newGasLimit,
address newDeliveryProviderAddress
) external payable returns (uint64 sequence);
/**
* @notice Requests a previously published delivery instruction to be redelivered
*
*
* This function must be called with `msg.value` equal to
* quoteDeliveryPrice(targetChain, newReceiverValue, newEncodedExecutionParameters, newDeliveryProviderAddress)
*
* @param deliveryVaaKey VaaKey identifying the wormhole message containing the
* previously published delivery instructions
* @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions
* @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param newEncodedExecutionParameters new encoded information on how to execute delivery that may impact pricing
* e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`
* @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @return sequence sequence number of published VAA containing redelivery instructions
*/
function resend(
VaaKey memory deliveryVaaKey,
uint16 targetChain,
uint256 newReceiverValue,
bytes memory newEncodedExecutionParameters,
address newDeliveryProviderAddress
) external payable returns (uint64 sequence);
/**
* @notice Returns the price to request a relay to chain `targetChain`, using the default delivery provider
*
* @param targetChain in Wormhole Chain ID format
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`.
* @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay
* @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused,
* if a refundAddress is specified
*/
function quoteEVMDeliveryPrice(
uint16 targetChain,
uint256 receiverValue,
uint256 gasLimit
) external view returns (uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused);
/**
* @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress`
*
* @param targetChain in Wormhole Chain ID format
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param gasLimit gas limit with which to call `targetAddress`.
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay
* @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused,
* if a refundAddress is specified
*/
function quoteEVMDeliveryPrice(
uint16 targetChain,
uint256 receiverValue,
uint256 gasLimit,
address deliveryProviderAddress
) external view returns (uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused);
/**
* @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress`
*
* @param targetChain in Wormhole Chain ID format
* @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)
* @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing
* e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay
* @return encodedExecutionInfo encoded information on how the delivery will be executed
* e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` and `targetChainRefundPerGasUnused`
* (which is the amount of target chain currency that will be refunded per unit of gas unused,
* if a refundAddress is specified)
*/
function quoteDeliveryPrice(
uint16 targetChain,
uint256 receiverValue,
bytes memory encodedExecutionParameters,
address deliveryProviderAddress
) external view returns (uint256 nativePriceQuote, bytes memory encodedExecutionInfo);
/**
* @notice Returns the (extra) amount of target chain currency that `targetAddress`
* will be called with, if the `paymentForExtraReceiverValue` field is set to `currentChainAmount`
*
* @param targetChain in Wormhole Chain ID format
* @param currentChainAmount The value that `paymentForExtraReceiverValue` will be set to
* @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider
* @return targetChainAmount The amount such that if `targetAddress` will be called with `msg.value` equal to
* receiverValue + targetChainAmount
*/
function quoteNativeForChain(
uint16 targetChain,
uint256 currentChainAmount,
address deliveryProviderAddress
) external view returns (uint256 targetChainAmount);
/**
* @notice Returns the address of the current default delivery provider
* @return deliveryProvider The address of (the default delivery provider)'s contract on this source
* chain. This must be a contract that implements IDeliveryProvider.
*/
function getDefaultDeliveryProvider() external view returns (address deliveryProvider);
}
/**
* @title IWormholeRelayerDelivery
* @notice The interface to execute deliveries. Only relevant for Delivery Providers
*/
interface IWormholeRelayerDelivery is IWormholeRelayerBase {
enum DeliveryStatus {
SUCCESS,
RECEIVER_FAILURE,
FORWARD_REQUEST_FAILURE,
FORWARD_REQUEST_SUCCESS
}
enum RefundStatus {
REFUND_SENT,
REFUND_FAIL,
CROSS_CHAIN_REFUND_SENT,
CROSS_CHAIN_REFUND_FAIL_PROVIDER_NOT_SUPPORTED,
CROSS_CHAIN_REFUND_FAIL_NOT_ENOUGH
}
/**
* @custom:member recipientContract - The target contract address
* @custom:member sourceChain - The chain which this delivery was requested from (in wormhole
* ChainID format)
* @custom:member sequence - The wormhole sequence number of the delivery VAA on the source chain
* corresponding to this delivery request
* @custom:member deliveryVaaHash - The hash of the delivery VAA corresponding to this delivery
* request
* @custom:member gasUsed - The amount of gas that was used to call your target contract
* @custom:member status:
* - RECEIVER_FAILURE, if the target contract reverts
* - SUCCESS, if the target contract doesn't revert and no forwards were requested
* - FORWARD_REQUEST_FAILURE, if the target contract doesn't revert, forwards were requested,
* but provided/leftover funds were not sufficient to cover them all
* - FORWARD_REQUEST_SUCCESS, if the target contract doesn't revert and all forwards are covered
* @custom:member additionalStatusInfo:
* - If status is SUCCESS or FORWARD_REQUEST_SUCCESS, then this is empty.
* - If status is RECEIVER_FAILURE, this is `RETURNDATA_TRUNCATION_THRESHOLD` bytes of the
* return data (i.e. potentially truncated revert reason information).
* - If status is FORWARD_REQUEST_FAILURE, this is also the revert data - the reason the forward failed.
* This will be either an encoded Cancelled, DeliveryProviderReverted, or DeliveryProviderPaymentFailed error
* @custom:member refundStatus - Result of the refund. REFUND_SUCCESS or REFUND_FAIL are for
* refunds where targetChain=refundChain; the others are for targetChain!=refundChain,
* where a cross chain refund is necessary
* @custom:member overridesInfo:
* - If not an override: empty bytes array
* - Otherwise: An encoded `DeliveryOverride`
*/
event Delivery(
address indexed recipientContract,
uint16 indexed sourceChain,
uint64 indexed sequence,
bytes32 deliveryVaaHash,
DeliveryStatus status,
uint256 gasUsed,
RefundStatus refundStatus,
bytes additionalStatusInfo,
bytes overridesInfo
);
/**
* @notice The delivery provider calls `deliver` to relay messages as described by one delivery instruction
*
* The delivery provider must pass in the specified (by VaaKeys[]) signed wormhole messages (VAAs) from the source chain
* as well as the signed wormhole message with the delivery instructions (the delivery VAA)
*
* The messages will be relayed to the target address (with the specified gas limit and receiver value) iff the following checks are met:
* - the delivery VAA has a valid signature
* - the delivery VAA's emitter is one of these WormholeRelayer contracts
* - the delivery provider passed in at least enough of this chain's currency as msg.value (enough meaning the maximum possible refund)
* - the instruction's target chain is this chain
* - the relayed signed VAAs match the descriptions in container.messages (the VAA hashes match, or the emitter address, sequence number pair matches, depending on the description given)
*
* @param encodedVMs - An array of signed wormhole messages (all from the same source chain
* transaction)
* @param encodedDeliveryVAA - Signed wormhole message from the source chain's WormholeRelayer
* contract with payload being the encoded delivery instruction container
* @param relayerRefundAddress - The address to which any refunds to the delivery provider
* should be sent
* @param deliveryOverrides - Optional overrides field which must be either an empty bytes array or
* an encoded DeliveryOverride struct
*/
function deliver(
bytes[] memory encodedVMs,
bytes memory encodedDeliveryVAA,
address payable relayerRefundAddress,
bytes memory deliveryOverrides
) external payable;
}
interface IWormholeRelayer is IWormholeRelayerDelivery, IWormholeRelayerSend {}
/*
* Errors thrown by IWormholeRelayer contract
*/
// Bound chosen by the following formula: `memoryWord * 4 + selectorSize`.
// This means that an error identifier plus four fixed size arguments should be available to developers.
// In the case of a `require` revert with error message, this should provide 2 memory word's worth of data.
uint256 constant RETURNDATA_TRUNCATION_THRESHOLD = 132;
//When msg.value was not equal to `delivery provider's quoted delivery price` + `paymentForExtraReceiverValue`
error InvalidMsgValue(uint256 msgValue, uint256 totalFee);
error RequestedGasLimitTooLow();
error DeliveryProviderDoesNotSupportTargetChain(address relayer, uint16 chainId);
error DeliveryProviderCannotReceivePayment();
//When calling `forward()` on the WormholeRelayer if no delivery is in progress
error NoDeliveryInProgress();
//When calling `delivery()` a second time even though a delivery is already in progress
error ReentrantDelivery(address msgSender, address lockedBy);
//When any other contract but the delivery target calls `forward()` on the WormholeRelayer while a
// delivery is in progress
error ForwardRequestFromWrongAddress(address msgSender, address deliveryTarget);
error InvalidPayloadId(uint8 parsed, uint8 expected);
error InvalidPayloadLength(uint256 received, uint256 expected);
error InvalidVaaKeyType(uint8 parsed);
error InvalidDeliveryVaa(string reason);
//When the delivery VAA (signed wormhole message with delivery instructions) was not emitted by the
// registered WormholeRelayer contract
error InvalidEmitter(bytes32 emitter, bytes32 registered, uint16 chainId);
error VaaKeysLengthDoesNotMatchVaasLength(uint256 keys, uint256 vaas);
error VaaKeysDoNotMatchVaas(uint8 index);
//When someone tries to call an external function of the WormholeRelayer that is only intended to be
// called by the WormholeRelayer itself (to allow retroactive reverts for atomicity)
error RequesterNotWormholeRelayer();
//When trying to relay a `DeliveryInstruction` to any other chain but the one it was specified for
error TargetChainIsNotThisChain(uint16 targetChain);
error ForwardNotSufficientlyFunded(uint256 amountOfFunds, uint256 amountOfFundsNeeded);
//When a `DeliveryOverride` contains a gas limit that's less than the original
error InvalidOverrideGasLimit();
//When a `DeliveryOverride` contains a receiver value that's less than the original
error InvalidOverrideReceiverValue();
//When a `DeliveryOverride` contains a 'refund per unit of gas unused' that's less than the original
error InvalidOverrideRefundPerGasUnused();
//When the delivery provider doesn't pass in sufficient funds (i.e. msg.value does not cover the
// maximum possible refund to the user)
error InsufficientRelayerFunds(uint256 msgValue, uint256 minimum);
//When a bytes32 field can't be converted into a 20 byte EVM address, because the 12 padding bytes
// are non-zero (duplicated from Utils.sol)
error NotAnEvmAddress(bytes32);// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import {IProposedOwnable} from "./interfaces/IProposedOwnable.sol";
/**
* @title ProposedOwnable
* @notice 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 via a two step process:
* 1. Call `proposeOwner`
* 2. Wait out the delay period
* 3. Call `acceptOwner`
*
* @dev 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.
*
* @dev The majority of this code was taken from the openzeppelin Ownable
* contract
*
*/
abstract contract ProposedOwnable is IProposedOwnable {
// ========== Custom Errors ===========
error ProposedOwnable__onlyOwner_notOwner();
error ProposedOwnable__onlyProposed_notProposedOwner();
error ProposedOwnable__ownershipDelayElapsed_delayNotElapsed();
error ProposedOwnable__proposeNewOwner_invalidProposal();
error ProposedOwnable__proposeNewOwner_noOwnershipChange();
error ProposedOwnable__renounceOwnership_noProposal();
error ProposedOwnable__renounceOwnership_invalidProposal();
// ============ Properties ============
address private _owner;
address private _proposed;
uint256 private _proposedOwnershipTimestamp;
uint256 private constant _delay = 7 days;
// ======== Getters =========
/**
* @notice Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @notice Returns the address of the proposed owner.
*/
function proposed() public view virtual returns (address) {
return _proposed;
}
/**
* @notice Returns the address of the proposed owner.
*/
function proposedTimestamp() public view virtual returns (uint256) {
return _proposedOwnershipTimestamp;
}
/**
* @notice Returns the delay period before a new owner can be accepted.
*/
function delay() public view virtual returns (uint256) {
return _delay;
}
/**
* @notice Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
if (_owner != msg.sender) revert ProposedOwnable__onlyOwner_notOwner();
_;
}
/**
* @notice Throws if called by any account other than the proposed owner.
*/
modifier onlyProposed() {
if (_proposed != msg.sender) revert ProposedOwnable__onlyProposed_notProposedOwner();
_;
}
/**
* @notice Throws if the ownership delay has not elapsed
*/
modifier ownershipDelayElapsed() {
// Ensure delay has elapsed
if ((block.timestamp - _proposedOwnershipTimestamp) <= _delay)
revert ProposedOwnable__ownershipDelayElapsed_delayNotElapsed();
_;
}
/**
* @notice Indicates if the ownership has been renounced() by
* checking if current owner is address(0)
*/
function renounced() public view returns (bool) {
return _owner == address(0);
}
// ======== External =========
/**
* @notice Sets the timestamp for an owner to be proposed, and sets the
* newly proposed owner as step 1 in a 2-step process
*/
function proposeNewOwner(address newlyProposed) public virtual onlyOwner {
// Contract as source of truth
if (_proposed == newlyProposed && _proposedOwnershipTimestamp != 0)
revert ProposedOwnable__proposeNewOwner_invalidProposal();
// Sanity check: reasonable proposal
if (_owner == newlyProposed) revert ProposedOwnable__proposeNewOwner_noOwnershipChange();
_setProposed(newlyProposed);
}
/**
* @notice Renounces ownership of the contract after a delay
*/
function renounceOwnership() public virtual onlyOwner ownershipDelayElapsed {
// Ensure there has been a proposal cycle started
if (_proposedOwnershipTimestamp == 0) revert ProposedOwnable__renounceOwnership_noProposal();
// Require proposed is set to 0
if (_proposed != address(0)) revert ProposedOwnable__renounceOwnership_invalidProposal();
// Emit event, set new owner, reset timestamp
_setOwner(address(0));
}
/**
* @notice Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function acceptProposedOwner() public virtual onlyProposed ownershipDelayElapsed {
// NOTE: no need to check if _owner == _proposed, because the _proposed
// is 0-d out and this check is implicitly enforced by modifier
// NOTE: no need to check if _proposedOwnershipTimestamp > 0 because
// the only time this would happen is if the _proposed was never
// set (will fail from modifier) or if the owner == _proposed (checked
// above)
// Emit event, set new owner, reset timestamp
_setOwner(_proposed);
}
// ======== Internal =========
function _setOwner(address newOwner) internal {
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
delete _proposedOwnershipTimestamp;
delete _proposed;
}
function _setProposed(address newlyProposed) private {
_proposedOwnershipTimestamp = block.timestamp;
_proposed = newlyProposed;
emit OwnershipProposed(newlyProposed);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/**
* @title IProposedOwnable
* @notice Defines a minimal interface for ownership with a two step proposal and acceptance
* process
*/
interface IProposedOwnable {
/**
* @dev This emits when change in ownership of a contract is proposed.
*/
event OwnershipProposed(address indexed proposedOwner);
/**
* @dev This emits when ownership of a contract changes.
*/
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @notice Get the address of the owner
* @return owner_ The address of the owner.
*/
function owner() external view returns (address owner_);
/**
* @notice Get the address of the proposed owner
* @return proposed_ The address of the proposed.
*/
function proposed() external view returns (address proposed_);
/**
* @notice Set the address of the proposed owner of the contract
* @param newlyProposed The proposed new owner of the contract
*/
function proposeNewOwner(address newlyProposed) external;
/**
* @notice Set the address of the proposed owner of the contract
*/
function acceptProposedOwner() external;
}{
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint32","name":"_mirrorDomain","type":"uint32"},{"internalType":"address","name":"_amb","type":"address"},{"internalType":"address","name":"_rootManager","type":"address"},{"internalType":"address","name":"_mirrorConnector","type":"address"},{"internalType":"uint256","name":"_gasCap","type":"uint256"},{"internalType":"uint16","name":"_mirrorWormholeChainId","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Connector__processMessage_notUsed","type":"error"},{"inputs":[],"name":"ProposedOwnable__onlyOwner_notOwner","type":"error"},{"inputs":[],"name":"ProposedOwnable__onlyProposed_notProposedOwner","type":"error"},{"inputs":[],"name":"ProposedOwnable__ownershipDelayElapsed_delayNotElapsed","type":"error"},{"inputs":[],"name":"ProposedOwnable__proposeNewOwner_invalidProposal","type":"error"},{"inputs":[],"name":"ProposedOwnable__proposeNewOwner_noOwnershipChange","type":"error"},{"inputs":[],"name":"ProposedOwnable__renounceOwnership_invalidProposal","type":"error"},{"inputs":[],"name":"ProposedOwnable__renounceOwnership_noProposal","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"GasCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MessageProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"encodedData","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previous","type":"address"},{"indexed":false,"internalType":"address","name":"current","type":"address"}],"name":"MirrorConnectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"mirrorDomain","type":"uint32"},{"indexed":false,"internalType":"address","name":"amb","type":"address"},{"indexed":false,"internalType":"address","name":"rootManager","type":"address"},{"indexed":false,"internalType":"address","name":"mirrorConnector","type":"address"}],"name":"NewConnector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposedOwner","type":"address"}],"name":"OwnershipProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previous","type":"address"},{"indexed":true,"internalType":"address","name":"updated","type":"address"}],"name":"RefundAddressUpdated","type":"event"},{"inputs":[],"name":"AMB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIRROR_DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIRROR_WORMHOLE_ID","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT_MANAGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptProposedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mirrorConnector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"processMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedWhMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newlyProposed","type":"address"}],"name":"proposeNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposedTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasLimit","type":"uint256"},{"internalType":"address","name":"_amb","type":"address"}],"name":"quoteEVMDeliveryPrice","outputs":[{"internalType":"uint256","name":"_cost","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"bytes[]","name":"","type":"bytes[]"},{"internalType":"bytes32","name":"_sourceAddress","type":"bytes32"},{"internalType":"uint16","name":"_sourceChain","type":"uint16"},{"internalType":"bytes32","name":"_deliveryHash","type":"bytes32"}],"name":"receiveWormholeMessages","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"refundAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"_encodedData","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasCap","type":"uint256"}],"name":"setGasCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mirrorConnector","type":"address"}],"name":"setMirrorConnector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_updated","type":"address"}],"name":"setRefundAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_expected","type":"address"}],"name":"verifySender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101206040523480156200001257600080fd5b5060405162001c2b38038062001c2b83398101604081905262000035916200039b565b818181898989898984848484846200004d33620001b3565b8463ffffffff16600003620000985760405162461bcd60e51b815260206004820152600c60248201526b32b6b83a3c903237b6b0b4b760a11b60448201526064015b60405180910390fd5b6001600160a01b038216620000e45760405162461bcd60e51b815260206004820152601160248201527032b6b83a3c903937b7ba26b0b730b3b2b960791b60448201526064016200008f565b63ffffffff8086166080526001600160a01b0380851660a05283811660c05290851660e0528116156200011c576200011c8162000218565b604080516001600160a01b0385811682528481166020830152831681830152905163ffffffff86811692908816917f4f9c27c2fe3f84576ea469d367d044da53c45e951617e8389f2b5ed8db9d25f09181900360600190a3505050505050505050506200018f816200028160201b60201c565b5061ffff811661010052620001a433620002c2565b50505050505050505062000431565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b60045460408051918252602082018390527f877a02cb809da0364d23adca3cd50c451b53f279d3df632e1fc11eb66335bce5910160405180910390a1600455565b6005546001600160a01b03908116908216036200030d5760405162461bcd60e51b81526020600482015260086024820152670858da185b99d95960c21b60448201526064016200008f565b6005546040516001600160a01b038084169216907f57b5839c3435f5b2eb2d2e286fb44ca7303d01d9b25a5d9c05c489523474285990600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b805163ffffffff811681146200037e57600080fd5b919050565b80516001600160a01b03811681146200037e57600080fd5b600080600080600080600060e0888a031215620003b757600080fd5b620003c28862000369565b9650620003d26020890162000369565b9550620003e26040890162000383565b9450620003f26060890162000383565b9350620004026080890162000383565b925060a0880151915060c088015161ffff811681146200042157600080fd5b8091505092959891949750929550565b60805160a05160c05160e05161010051611776620004b5600039600081816102af0152818161065501528181610bab01526112130152600081816102040152610db60152600081816103c5015281816105980152610d8f01526000818161051401528181610701015281816107a20152610b460152600061037101526117766000f3fe6080604052600436106101855760003560e01c80635f61e3ec116100d1578063b1f8100d1161008a578063d1851c9211610064578063d1851c92146104c5578063d232c220146104e3578063d69f9d6114610502578063db1b76591461053657600080fd5b8063b1f8100d14610470578063c5b350df14610490578063cc394283146104a557600080fd5b80635f61e3ec146103b357806368742da6146103e75780636a42b8f814610407578063715018a61461041d5780637850b020146104325780638da5cb5b1461045257600080fd5b80633cf52ffb1161013e5780634ff746f6116101185780634ff746f61461032c578063529dca321461034c57806352a9674b1461035f5780635bd11efc1461039357600080fd5b80633cf52ffb146102e457806348e6fa23146102f95780634d93538b1461030c57600080fd5b8063047dbeb8146101915780630cb61f6c146101ba57806314168416146101f257806315b75bea1461023b57806318c817091461025d578063194ea9961461029d57600080fd5b3661018c57005b600080fd5b34801561019d57600080fd5b506101a760045481565b6040519081526020015b60405180910390f35b3480156101c657600080fd5b506005546101da906001600160a01b031681565b6040516001600160a01b0390911681526020016101b1565b3480156101fe57600080fd5b506102267f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016101b1565b34801561024757600080fd5b5061025b6102563660046112b0565b610556565b005b34801561026957600080fd5b5061028d6102783660046112d2565b60066020526000908152604090205460ff1681565b60405190151581526020016101b1565b3480156102a957600080fd5b506102d17f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff90911681526020016101b1565b3480156102f057600080fd5b506002546101a7565b61025b6103073660046113a2565b61058d565b34801561031857600080fd5b506101a7610327366004611406565b610642565b34801561033857600080fd5b5061025b610347366004611432565b6106f6565b61025b61035a366004611481565b61079c565b34801561036b57600080fd5b506102267f000000000000000000000000000000000000000000000000000000000000000081565b34801561039f57600080fd5b5061025b6103ae3660046112b0565b6107e0565b3480156103bf57600080fd5b506101da7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103f357600080fd5b5061025b6104023660046112b0565b610814565b34801561041357600080fd5b5062093a806101a7565b34801561042957600080fd5b5061025b610891565b34801561043e57600080fd5b5061025b61044d3660046112d2565b610945565b34801561045e57600080fd5b506000546001600160a01b03166101da565b34801561047c57600080fd5b5061025b61048b3660046112b0565b610979565b34801561049c57600080fd5b5061025b610a17565b3480156104b157600080fd5b506003546101da906001600160a01b031681565b3480156104d157600080fd5b506001546001600160a01b03166101da565b3480156104ef57600080fd5b506000546001600160a01b03161561028d565b34801561050e57600080fd5b506101da7f000000000000000000000000000000000000000000000000000000000000000081565b34801561054257600080fd5b5061028d6105513660046112b0565b610a87565b6000546001600160a01b03163314610581576040516311a8a1bb60e31b815260040160405180910390fd5b61058a81610a98565b50565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105f95760405162461bcd60e51b815260206004820152600c60248201526b10b937b7ba26b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6106038282610b3d565b7fdcaa37a042a0087de79018c629bbd29cee82ca80bd9be394e1696bf9e9355077828233604051610636939291906115d0565b60405180910390a15050565b6000816001600160a01b031663c23ee3c37f0000000000000000000000000000000000000000000000000000000000000000600061067f87610b7a565b6040516001600160e01b031960e086901b16815261ffff9093166004840152602483019190915260448201526064016040805180830381865afa1580156106ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ee919061160e565b509392505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107575760405162461bcd60e51b81526004016105f09060208082526004908201526310a0a6a160e11b604082015260600190565b61076081610b90565b7fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced8133604051610791929190611632565b60405180910390a150565b6107c7827f000000000000000000000000000000000000000000000000000000000000000083610ba9565b6107d96107d384610cc3565b86610d06565b5050505050565b6000546001600160a01b0316331461080b576040516311a8a1bb60e31b815260040160405180910390fd5b61058a81610e6b565b6000546001600160a01b0316331461083f576040516311a8a1bb60e31b815260040160405180910390fd5b4761084a8282610ed4565b816001600160a01b03167feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d8260405161088591815260200190565b60405180910390a25050565b6000546001600160a01b031633146108bc576040516311a8a1bb60e31b815260040160405180910390fd5b62093a80600254426108ce919061165c565b116108ec576040516324e0285f60e21b815260040160405180910390fd5b60025460000361090f57604051630e4b303f60e21b815260040160405180910390fd5b6001546001600160a01b031615610939576040516323295ef960e01b815260040160405180910390fd5b6109436000610ff2565b565b6000546001600160a01b03163314610970576040516311a8a1bb60e31b815260040160405180910390fd5b61058a81611057565b6000546001600160a01b031633146109a4576040516311a8a1bb60e31b815260040160405180910390fd5b6001546001600160a01b0382811691161480156109c2575060025415155b156109e0576040516311bc066560e11b815260040160405180910390fd5b6000546001600160a01b03808316911603610a0e57604051634a2fb73f60e11b815260040160405180910390fd5b61058a81611098565b6001546001600160a01b03163314610a42576040516311a7f27160e11b815260040160405180910390fd5b62093a8060025442610a54919061165c565b11610a72576040516324e0285f60e21b815260040160405180910390fd5b600154610943906001600160a01b0316610ff2565b6000610a92826110e6565b92915050565b6005546001600160a01b0390811690821603610ae15760405162461bcd60e51b81526020600482015260086024820152670858da185b99d95960c21b60448201526064016105f0565b6005546040516001600160a01b038084169216907f57b5839c3435f5b2eb2d2e286fb44ca7303d01d9b25a5d9c05c489523474285990600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b600354610b76907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031684846110ff565b5050565b6000600454821115610b8c5760045491505b5090565b6040516316c2fdb560e21b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168361ffff1614610c105760405162461bcd60e51b815260206004820152600d60248201526c10b9b7bab931b29031b430b4b760991b60448201526064016105f0565b336001600160a01b03831614610c535760405162461bcd60e51b815260206004820152600860248201526710b932b630bcb2b960c11b60448201526064016105f0565b60008181526006602052604090205460ff1615610ca65760405162461bcd60e51b8152602060048201526011602482015270185b1c9958591e481c1c9bd8d95cdcd959607a1b60448201526064016105f0565b6000908152600660205260409020805460ff191660011790555050565b600060a082901c15610b8c5760405162461bcd60e51b815260206004820152600c60248201526b2165766d206164647265737360a01b60448201526064016105f0565b610d0f826110e6565b610d4a5760405162461bcd60e51b815260206004820152600c60248201526b10b61921b7b73732b1ba37b960a11b60448201526064016105f0565b8051602014610d855760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b60448201526064016105f0565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016638e7d93fa7f0000000000000000000000000000000000000000000000000000000000000000610dde8461167d565b6040516001600160e01b031960e085901b16815263ffffffff9290921660048301526024820152604401600060405180830381600087803b158015610e2257600080fd5b505af1158015610e36573d6000803e3d6000fd5b505050507fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced8133604051610636929190611632565b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b80471015610f245760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016105f0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610f71576040519150601f19603f3d011682016040523d82523d6000602084013e610f76565b606091505b5050905080610fed5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105f0565b505050565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b60045460408051918252602082018390527f877a02cb809da0364d23adca3cd50c451b53f279d3df632e1fc11eb66335bce5910160405180910390a1600455565b42600255600180546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b6003546000906001600160a01b03838116911614610a92565b815160201461113f5760405162461bcd60e51b815260206004820152600c60248201526b042c8c2e8c240d8cadccee8d60a31b60448201526064016105f0565b80516020146111875760405162461bcd60e51b8152602060048201526014602482015273042cadcc6dec8cac840c8c2e8c240d8cadccee8d60631b60448201526064016105f0565b60008180602001905181019061119d91906116a4565b905060006111ab8287610642565b90503481146111e95760405162461bcd60e51b815260206004820152600a602482015269216d73672e76616c756560b01b60448201526064016105f0565b6005546040516312d729bd60e21b81526001600160a01b0380891692634b5ca6f4928592611248927f0000000000000000000000000000000000000000000000000000000000000000928c928c926000928c92879216906004016116bd565b60206040518083038185885af1158015611266573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061128b9190611716565b50505050505050565b80356001600160a01b03811681146112ab57600080fd5b919050565b6000602082840312156112c257600080fd5b6112cb82611294565b9392505050565b6000602082840312156112e457600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561132a5761132a6112eb565b604052919050565b600082601f83011261134357600080fd5b813567ffffffffffffffff81111561135d5761135d6112eb565b611370601f8201601f1916602001611301565b81815284602083860101111561138557600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156113b557600080fd5b823567ffffffffffffffff808211156113cd57600080fd5b6113d986838701611332565b935060208501359150808211156113ef57600080fd5b506113fc85828601611332565b9150509250929050565b6000806040838503121561141957600080fd5b8235915061142960208401611294565b90509250929050565b60006020828403121561144457600080fd5b813567ffffffffffffffff81111561145b57600080fd5b61146784828501611332565b949350505050565b803561ffff811681146112ab57600080fd5b600080600080600060a0868803121561149957600080fd5b853567ffffffffffffffff808211156114b157600080fd5b6114bd89838a01611332565b96506020915081880135818111156114d457600080fd5b8801601f81018a136114e557600080fd5b8035828111156114f7576114f76112eb565b8060051b611506858201611301565b918252828101850191858101908d84111561152057600080fd5b86850192505b8383101561155c5782358681111561153e5760008081fd5b61154c8f8983890101611332565b8352509186019190860190611526565b809a5050505050505050604086013592506115796060870161146f565b949793965091946080013592915050565b6000815180845260005b818110156115b057602081850181015186830182015201611594565b506000602082860101526020601f19601f83011685010191505092915050565b6060815260006115e3606083018661158a565b82810360208401526115f5818661158a565b91505060018060a01b0383166040830152949350505050565b6000806040838503121561162157600080fd5b505080516020909101519092909150565b604081526000611645604083018561158a565b905060018060a01b03831660208301529392505050565b81810381811115610a9257634e487b7160e01b600052601160045260246000fd5b8051602080830151919081101561169e576000198160200360031b1b821691505b50919050565b6000602082840312156116b657600080fd5b5051919050565b600061ffff808a16835260018060a01b03808a16602085015260e060408501526116ea60e085018a61158a565b925087606085015286608085015281861660a085015280851660c0850152505098975050505050505050565b60006020828403121561172857600080fd5b815167ffffffffffffffff811681146112cb57600080fdfea264697066735822122077ef5ddd4f84658dcd6f5d78758dafb44d91461cf057c309b77b296faf446eec64736f6c6343000811003300000000000000000000000000000000000000000000000000000000006574680000000000000000000000000000000000000000000000000000000000626e6200000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000493e00000000000000000000000000000000000000000000000000000000000000004
Deployed Bytecode
0x6080604052600436106101855760003560e01c80635f61e3ec116100d1578063b1f8100d1161008a578063d1851c9211610064578063d1851c92146104c5578063d232c220146104e3578063d69f9d6114610502578063db1b76591461053657600080fd5b8063b1f8100d14610470578063c5b350df14610490578063cc394283146104a557600080fd5b80635f61e3ec146103b357806368742da6146103e75780636a42b8f814610407578063715018a61461041d5780637850b020146104325780638da5cb5b1461045257600080fd5b80633cf52ffb1161013e5780634ff746f6116101185780634ff746f61461032c578063529dca321461034c57806352a9674b1461035f5780635bd11efc1461039357600080fd5b80633cf52ffb146102e457806348e6fa23146102f95780634d93538b1461030c57600080fd5b8063047dbeb8146101915780630cb61f6c146101ba57806314168416146101f257806315b75bea1461023b57806318c817091461025d578063194ea9961461029d57600080fd5b3661018c57005b600080fd5b34801561019d57600080fd5b506101a760045481565b6040519081526020015b60405180910390f35b3480156101c657600080fd5b506005546101da906001600160a01b031681565b6040516001600160a01b0390911681526020016101b1565b3480156101fe57600080fd5b506102267f0000000000000000000000000000000000000000000000000000000000626e6281565b60405163ffffffff90911681526020016101b1565b34801561024757600080fd5b5061025b6102563660046112b0565b610556565b005b34801561026957600080fd5b5061028d6102783660046112d2565b60066020526000908152604090205460ff1681565b60405190151581526020016101b1565b3480156102a957600080fd5b506102d17f000000000000000000000000000000000000000000000000000000000000000481565b60405161ffff90911681526020016101b1565b3480156102f057600080fd5b506002546101a7565b61025b6103073660046113a2565b61058d565b34801561031857600080fd5b506101a7610327366004611406565b610642565b34801561033857600080fd5b5061025b610347366004611432565b6106f6565b61025b61035a366004611481565b61079c565b34801561036b57600080fd5b506102267f000000000000000000000000000000000000000000000000000000000065746881565b34801561039f57600080fd5b5061025b6103ae3660046112b0565b6107e0565b3480156103bf57600080fd5b506101da7f000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a81565b3480156103f357600080fd5b5061025b6104023660046112b0565b610814565b34801561041357600080fd5b5062093a806101a7565b34801561042957600080fd5b5061025b610891565b34801561043e57600080fd5b5061025b61044d3660046112d2565b610945565b34801561045e57600080fd5b506000546001600160a01b03166101da565b34801561047c57600080fd5b5061025b61048b3660046112b0565b610979565b34801561049c57600080fd5b5061025b610a17565b3480156104b157600080fd5b506003546101da906001600160a01b031681565b3480156104d157600080fd5b506001546001600160a01b03166101da565b3480156104ef57600080fd5b506000546001600160a01b03161561028d565b34801561050e57600080fd5b506101da7f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d89491181565b34801561054257600080fd5b5061028d6105513660046112b0565b610a87565b6000546001600160a01b03163314610581576040516311a8a1bb60e31b815260040160405180910390fd5b61058a81610a98565b50565b336001600160a01b037f000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a16146105f95760405162461bcd60e51b815260206004820152600c60248201526b10b937b7ba26b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6106038282610b3d565b7fdcaa37a042a0087de79018c629bbd29cee82ca80bd9be394e1696bf9e9355077828233604051610636939291906115d0565b60405180910390a15050565b6000816001600160a01b031663c23ee3c37f0000000000000000000000000000000000000000000000000000000000000004600061067f87610b7a565b6040516001600160e01b031960e086901b16815261ffff9093166004840152602483019190915260448201526064016040805180830381865afa1580156106ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ee919061160e565b509392505050565b336001600160a01b037f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d89491116146107575760405162461bcd60e51b81526004016105f09060208082526004908201526310a0a6a160e11b604082015260600190565b61076081610b90565b7fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced8133604051610791929190611632565b60405180910390a150565b6107c7827f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d89491183610ba9565b6107d96107d384610cc3565b86610d06565b5050505050565b6000546001600160a01b0316331461080b576040516311a8a1bb60e31b815260040160405180910390fd5b61058a81610e6b565b6000546001600160a01b0316331461083f576040516311a8a1bb60e31b815260040160405180910390fd5b4761084a8282610ed4565b816001600160a01b03167feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d8260405161088591815260200190565b60405180910390a25050565b6000546001600160a01b031633146108bc576040516311a8a1bb60e31b815260040160405180910390fd5b62093a80600254426108ce919061165c565b116108ec576040516324e0285f60e21b815260040160405180910390fd5b60025460000361090f57604051630e4b303f60e21b815260040160405180910390fd5b6001546001600160a01b031615610939576040516323295ef960e01b815260040160405180910390fd5b6109436000610ff2565b565b6000546001600160a01b03163314610970576040516311a8a1bb60e31b815260040160405180910390fd5b61058a81611057565b6000546001600160a01b031633146109a4576040516311a8a1bb60e31b815260040160405180910390fd5b6001546001600160a01b0382811691161480156109c2575060025415155b156109e0576040516311bc066560e11b815260040160405180910390fd5b6000546001600160a01b03808316911603610a0e57604051634a2fb73f60e11b815260040160405180910390fd5b61058a81611098565b6001546001600160a01b03163314610a42576040516311a7f27160e11b815260040160405180910390fd5b62093a8060025442610a54919061165c565b11610a72576040516324e0285f60e21b815260040160405180910390fd5b600154610943906001600160a01b0316610ff2565b6000610a92826110e6565b92915050565b6005546001600160a01b0390811690821603610ae15760405162461bcd60e51b81526020600482015260086024820152670858da185b99d95960c21b60448201526064016105f0565b6005546040516001600160a01b038084169216907f57b5839c3435f5b2eb2d2e286fb44ca7303d01d9b25a5d9c05c489523474285990600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b600354610b76907f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911906001600160a01b031684846110ff565b5050565b6000600454821115610b8c5760045491505b5090565b6040516316c2fdb560e21b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000461ffff168361ffff1614610c105760405162461bcd60e51b815260206004820152600d60248201526c10b9b7bab931b29031b430b4b760991b60448201526064016105f0565b336001600160a01b03831614610c535760405162461bcd60e51b815260206004820152600860248201526710b932b630bcb2b960c11b60448201526064016105f0565b60008181526006602052604090205460ff1615610ca65760405162461bcd60e51b8152602060048201526011602482015270185b1c9958591e481c1c9bd8d95cdcd959607a1b60448201526064016105f0565b6000908152600660205260409020805460ff191660011790555050565b600060a082901c15610b8c5760405162461bcd60e51b815260206004820152600c60248201526b2165766d206164647265737360a01b60448201526064016105f0565b610d0f826110e6565b610d4a5760405162461bcd60e51b815260206004820152600c60248201526b10b61921b7b73732b1ba37b960a11b60448201526064016105f0565b8051602014610d855760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b60448201526064016105f0565b6001600160a01b037f000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a16638e7d93fa7f0000000000000000000000000000000000000000000000000000000000626e62610dde8461167d565b6040516001600160e01b031960e085901b16815263ffffffff9290921660048301526024820152604401600060405180830381600087803b158015610e2257600080fd5b505af1158015610e36573d6000803e3d6000fd5b505050507fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced8133604051610636929190611632565b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b80471015610f245760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016105f0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610f71576040519150601f19603f3d011682016040523d82523d6000602084013e610f76565b606091505b5050905080610fed5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105f0565b505050565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b60045460408051918252602082018390527f877a02cb809da0364d23adca3cd50c451b53f279d3df632e1fc11eb66335bce5910160405180910390a1600455565b42600255600180546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b6003546000906001600160a01b03838116911614610a92565b815160201461113f5760405162461bcd60e51b815260206004820152600c60248201526b042c8c2e8c240d8cadccee8d60a31b60448201526064016105f0565b80516020146111875760405162461bcd60e51b8152602060048201526014602482015273042cadcc6dec8cac840c8c2e8c240d8cadccee8d60631b60448201526064016105f0565b60008180602001905181019061119d91906116a4565b905060006111ab8287610642565b90503481146111e95760405162461bcd60e51b815260206004820152600a602482015269216d73672e76616c756560b01b60448201526064016105f0565b6005546040516312d729bd60e21b81526001600160a01b0380891692634b5ca6f4928592611248927f0000000000000000000000000000000000000000000000000000000000000004928c928c926000928c92879216906004016116bd565b60206040518083038185885af1158015611266573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061128b9190611716565b50505050505050565b80356001600160a01b03811681146112ab57600080fd5b919050565b6000602082840312156112c257600080fd5b6112cb82611294565b9392505050565b6000602082840312156112e457600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561132a5761132a6112eb565b604052919050565b600082601f83011261134357600080fd5b813567ffffffffffffffff81111561135d5761135d6112eb565b611370601f8201601f1916602001611301565b81815284602083860101111561138557600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156113b557600080fd5b823567ffffffffffffffff808211156113cd57600080fd5b6113d986838701611332565b935060208501359150808211156113ef57600080fd5b506113fc85828601611332565b9150509250929050565b6000806040838503121561141957600080fd5b8235915061142960208401611294565b90509250929050565b60006020828403121561144457600080fd5b813567ffffffffffffffff81111561145b57600080fd5b61146784828501611332565b949350505050565b803561ffff811681146112ab57600080fd5b600080600080600060a0868803121561149957600080fd5b853567ffffffffffffffff808211156114b157600080fd5b6114bd89838a01611332565b96506020915081880135818111156114d457600080fd5b8801601f81018a136114e557600080fd5b8035828111156114f7576114f76112eb565b8060051b611506858201611301565b918252828101850191858101908d84111561152057600080fd5b86850192505b8383101561155c5782358681111561153e5760008081fd5b61154c8f8983890101611332565b8352509186019190860190611526565b809a5050505050505050604086013592506115796060870161146f565b949793965091946080013592915050565b6000815180845260005b818110156115b057602081850181015186830182015201611594565b506000602082860101526020601f19601f83011685010191505092915050565b6060815260006115e3606083018661158a565b82810360208401526115f5818661158a565b91505060018060a01b0383166040830152949350505050565b6000806040838503121561162157600080fd5b505080516020909101519092909150565b604081526000611645604083018561158a565b905060018060a01b03831660208301529392505050565b81810381811115610a9257634e487b7160e01b600052601160045260246000fd5b8051602080830151919081101561169e576000198160200360031b1b821691505b50919050565b6000602082840312156116b657600080fd5b5051919050565b600061ffff808a16835260018060a01b03808a16602085015260e060408501526116ea60e085018a61158a565b925087606085015286608085015281861660a085015280851660c0850152505098975050505050505050565b60006020828403121561172857600080fd5b815167ffffffffffffffff811681146112cb57600080fdfea264697066735822122077ef5ddd4f84658dcd6f5d78758dafb44d91461cf057c309b77b296faf446eec64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000006574680000000000000000000000000000000000000000000000000000000000626e6200000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000493e00000000000000000000000000000000000000000000000000000000000000004
-----Decoded View---------------
Arg [0] : _domain (uint32): 6648936
Arg [1] : _mirrorDomain (uint32): 6450786
Arg [2] : _amb (address): 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911
Arg [3] : _rootManager (address): 0x523AB7424AD126809b1d7A134eb6E0ee414C9B3A
Arg [4] : _mirrorConnector (address): 0x0000000000000000000000000000000000000000
Arg [5] : _gasCap (uint256): 300000
Arg [6] : _mirrorWormholeChainId (uint16): 4
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000657468
Arg [1] : 0000000000000000000000000000000000000000000000000000000000626e62
Arg [2] : 00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
Arg [3] : 000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000000000000000000000000000000000000000493e0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.