Cuentas
0x7f...da74
0x7f...da74

0x7f...da74

$500
¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.18+commit.87f61d96
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 9: Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
Código Fuente del Contrato
Archivo 2 de 9: GasOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IGasOracle} from "./interfaces/IGasOracle.sol";

/**
 * @title GasOracle
 * @dev A contract that provides gas price and native token USD price data on other blockchains.
 */
contract GasOracle is Ownable, IGasOracle {
    struct ChainData {
        // price of the chain's native token in USD
        uint128 price;
        // price of a gas unit in the chain's native token with precision according to the const ORACLE_PRECISION
        uint128 gasPrice;
    }
    uint private constant ORACLE_PRECISION = 18;
    uint private constant ORACLE_SCALING_FACTOR = 10 ** ORACLE_PRECISION;
    // number to divide by to change precision from gas oracle price precision to chain precision
    uint private immutable fromOracleToChainScalingFactor;

    mapping(uint chainId => ChainData) public override chainData;
    // current chain ID
    uint public immutable override chainId;

    constructor(uint chainId_, uint chainPrecision) {
        chainId = chainId_;
        fromOracleToChainScalingFactor = 10 ** (ORACLE_PRECISION - chainPrecision);
    }

    /**
     * @notice Sets the chain data for a given chain ID.
     * @param chainId_ The ID of the given chain to set data for.
     * @param price_ The price of the given chain's native token in USD.
     * @param gasPrice The price of a gas unit in the given chain's native token (with precision according to the const
     * `ORACLE_PRECISION`).
     */
    function setChainData(uint chainId_, uint128 price_, uint128 gasPrice) external override onlyOwner {
        chainData[chainId_].price = price_;
        chainData[chainId_].gasPrice = gasPrice;
    }

    /**
     * @notice Sets only the price for a given chain ID.
     * @param chainId_ The ID of the given chain to set the price for.
     * @param price_ The price of the given chain's native token in USD.
     */
    function setPrice(uint chainId_, uint128 price_) external override onlyOwner {
        chainData[chainId_].price = price_;
    }

    /**
     * @notice Sets only the gas price for a given chain ID.
     * @param chainId_ The ID of the given chain to set the gas price for.
     * @param gasPrice The price of a gas unit in the given chain's native token (with precision according to the const
     * `ORACLE_PRECISION`).
     */
    function setGasPrice(uint chainId_, uint128 gasPrice) external override onlyOwner {
        chainData[chainId_].gasPrice = gasPrice;
    }

    /**
     * @notice Calculates the gas cost of a transaction on another chain in the current chain's native token.
     * @param otherChainId The ID of the chain for which to get the gas cost.
     * @param gasAmount The amount of gas used in a transaction.
     * @return The gas cost of a transaction in the current chain's native token
     */
    function getTransactionGasCostInNativeToken(
        uint otherChainId,
        uint gasAmount
    ) external view override returns (uint) {
        return
            (chainData[otherChainId].gasPrice * gasAmount * chainData[otherChainId].price) /
            chainData[chainId].price /
            fromOracleToChainScalingFactor;
    }

    /**
     * @notice Calculates the gas cost of a transaction on another chain in USD.
     * @param otherChainId The ID of the chain for which to get the gas cost.
     * @param gasAmount The amount of gas used in a transaction.
     * @return The gas cost of a transaction in USD with precision of `ORACLE_PRECISION`
     */
    function getTransactionGasCostInUSD(uint otherChainId, uint gasAmount) external view override returns (uint) {
        return (chainData[otherChainId].gasPrice * gasAmount * chainData[otherChainId].price) / ORACLE_SCALING_FACTOR;
    }

    /**
     * @notice Get the cross-rate between the two chains' native tokens.
     * @param otherChainId The ID of the other chain to get the cross-rate for.
     */
    function crossRate(uint otherChainId) external view override returns (uint) {
        return (chainData[otherChainId].price * ORACLE_SCALING_FACTOR) / chainData[chainId].price;
    }

    /**
     * @notice Get the price of a given chain's native token in USD.
     * @param chainId_ The ID of the given chain to get the price.
     * @return the price of the given chain's native token in USD with precision of const ORACLE_PRECISION
     */
    function price(uint chainId_) external view override returns (uint) {
        return chainData[chainId_].price;
    }

    fallback() external payable {
        revert("Unsupported");
    }

    receive() external payable {
        revert("Unsupported");
    }
}
Código Fuente del Contrato
Archivo 3 de 9: GasUsage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IGasOracle} from "./interfaces/IGasOracle.sol";

/**
 * @dev Contract module which allows children to store typical gas usage of a certain transaction on another chain.
 */
abstract contract GasUsage is Ownable {
    IGasOracle internal gasOracle;
    mapping(uint chainId => uint amount) public gasUsage;

    constructor(IGasOracle gasOracle_) {
        gasOracle = gasOracle_;
    }

    /**
     * @dev Sets the amount of gas used for a transaction on a given chain.
     * @param chainId The ID of the chain.
     * @param gasAmount The amount of gas used on the chain.
     */
    function setGasUsage(uint chainId, uint gasAmount) external onlyOwner {
        gasUsage[chainId] = gasAmount;
    }

    /**
     * @dev Sets the Gas Oracle contract address.
     * @param gasOracle_ The address of the Gas Oracle contract.
     */
    function setGasOracle(IGasOracle gasOracle_) external onlyOwner {
        gasOracle = gasOracle_;
    }

    /**
     * @notice Get the gas cost of a transaction on another chain in the current chain's native token.
     * @param chainId The ID of the chain for which to get the gas cost.
     * @return The calculated gas cost of the transaction in the current chain's native token
     */
    function getTransactionCost(uint chainId) external view returns (uint) {
        unchecked {
            return gasOracle.getTransactionGasCostInNativeToken(chainId, gasUsage[chainId]);
        }
    }
}
Código Fuente del Contrato
Archivo 4 de 9: HashUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

library HashUtils {
    function replaceChainBytes(
        bytes32 data,
        uint8 sourceChainId,
        uint8 destinationChainId
    ) internal pure returns (bytes32 result) {
        assembly {
            mstore(0x00, data)
            mstore8(0x00, sourceChainId)
            mstore8(0x01, destinationChainId)
            result := mload(0x0)
        }
    }

    function hashWithSender(bytes32 message, bytes32 sender) internal pure returns (bytes32 result) {
        assembly {
            mstore(0x00, message)
            mstore(0x20, sender)
            result := or(
                and(
                    message,
                    0xffff000000000000000000000000000000000000000000000000000000000000 // First 2 bytes
                ),
                and(
                    keccak256(0x00, 0x40),
                    0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // Last 30 bytes
                )
            )
        }
    }

    function hashWithSenderAddress(bytes32 message, address sender) internal pure returns (bytes32 result) {
        assembly {
            mstore(0x00, message)
            mstore(0x20, sender)
            result := or(
                and(
                    message,
                    0xffff000000000000000000000000000000000000000000000000000000000000 // First 2 bytes
                ),
                and(
                    keccak256(0x00, 0x40),
                    0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // Last 30 bytes
                )
            )
        }
    }

    function hashed(bytes32 message) internal pure returns (bytes32 result) {
        assembly {
            mstore(0x00, message)
            result := keccak256(0x00, 0x20)
        }
    }
}
Código Fuente del Contrato
Archivo 5 de 9: IGasOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IGasOracle {
    function chainData(uint chainId) external view returns (uint128 price, uint128 gasPrice);

    function chainId() external view returns (uint);

    function crossRate(uint otherChainId) external view returns (uint);

    function getTransactionGasCostInNativeToken(uint otherChainId, uint256 gasAmount) external view returns (uint);

    function getTransactionGasCostInUSD(uint otherChainId, uint256 gasAmount) external view returns (uint);

    function price(uint chainId) external view returns (uint);

    function setChainData(uint chainId, uint128 price, uint128 gasPrice) external;

    function setGasPrice(uint chainId, uint128 gasPrice) external;

    function setPrice(uint chainId, uint128 price) external;
}
Código Fuente del Contrato
Archivo 6 de 9: IMessenger.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IMessenger {
    function sentMessagesBlock(bytes32 message) external view returns (uint);

    function receivedMessages(bytes32 message) external view returns (uint);

    function sendMessage(bytes32 message) external payable;

    function receiveMessage(bytes32 message, uint v1v2, bytes32 r1, bytes32 s1, bytes32 r2, bytes32 s2) external;
}
Código Fuente del Contrato
Archivo 7 de 9: IWormhole.sol
// contracts/Messages.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.18;

interface Structs {
    struct Provider {
        uint16 chainId;
        uint16 governanceChainId;
        bytes32 governanceContract;
    }

    struct GuardianSet {
        address[] keys;
        uint32 expirationTime;
    }

    struct Signature {
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint8 guardianIndex;
    }

    struct VM {
        uint8 version;
        uint32 timestamp;
        uint32 nonce;
        uint16 emitterChainId;
        bytes32 emitterAddress;
        uint64 sequence;
        uint8 consistencyLevel;
        bytes payload;
        uint32 guardianSetIndex;
        Signature[] signatures;
        bytes32 hash;
    }
}

interface IWormhole is Structs {
    event LogMessagePublished(
        address indexed sender,
        uint64 sequence,
        uint32 nonce,
        bytes payload,
        uint8 consistencyLevel
    );

    function publishMessage(
        uint32 nonce,
        bytes memory payload,
        uint8 consistencyLevel
    ) external payable returns (uint64 sequence);

    function parseAndVerifyVM(
        bytes calldata encodedVM
    ) external view returns (Structs.VM memory vm, bool valid, string memory reason);

    function verifyVM(Structs.VM memory vm) external view returns (bool valid, string memory reason);

    function verifySignatures(
        bytes32 hash,
        Structs.Signature[] memory signatures,
        Structs.GuardianSet memory guardianSet
    ) external pure returns (bool valid, string memory reason);

    function parseVM(bytes memory encodedVM) external pure returns (Structs.VM memory vm);

    function getGuardianSet(uint32 index) external view returns (Structs.GuardianSet memory);

    function getCurrentGuardianSetIndex() external view returns (uint32);

    function getGuardianSetExpiry() external view returns (uint32);

    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);

    function isInitialized(address impl) external view returns (bool);

    function chainId() external view returns (uint16);

    function governanceChainId() external view returns (uint16);

    function governanceContract() external view returns (bytes32);

    function messageFee() external view returns (uint);
}
Código Fuente del Contrato
Archivo 8 de 9: Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
Código Fuente del Contrato
Archivo 9 de 9: WormholeMessenger.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IGasOracle} from "./interfaces/IGasOracle.sol";
import {IMessenger} from "./interfaces/IMessenger.sol";
import {IWormhole} from "./interfaces/IWormhole.sol";
import {GasUsage} from "./GasUsage.sol";
import {GasOracle} from "./GasOracle.sol";
import {HashUtils} from "./libraries/HashUtils.sol";

contract WormholeMessenger is Ownable, GasUsage {
    using HashUtils for bytes32;

    IWormhole private immutable wormhole;
    uint public immutable chainId;
    bytes32 public otherChainIds;

    uint32 private nonce;
    uint8 private commitmentLevel;

    mapping(uint16 chainId => bytes32 wormholeMessengerAddress) private otherWormholeMessengers;

    mapping(bytes32 messageHash => uint isReceived) public receivedMessages;
    mapping(bytes32 messageHash => uint isSent) public sentMessages;

    event MessageSent(bytes32 indexed message, uint64 sequence);
    event MessageReceived(bytes32 indexed message, uint64 sequence);
    event Received(address, uint);

    constructor(
        uint chainId_,
        bytes32 otherChainIds_,
        IWormhole wormhole_,
        uint8 commitmentLevel_,
        IGasOracle gasOracle_
    ) GasUsage(gasOracle_) {
        chainId = chainId_;
        otherChainIds = otherChainIds_;
        wormhole = wormhole_;
        commitmentLevel = commitmentLevel_;
    }

    function sendMessage(bytes32 message) external payable {
        require(uint8(message[0]) == chainId, "WormholeMessenger: wrong chainId");
        require(otherChainIds[uint8(message[1])] != 0, "Messenger: wrong destination");
        bytes32 messageWithSender = message.hashWithSenderAddress(msg.sender);

        uint32 nonce_ = nonce;

        uint64 sequence = wormhole.publishMessage(nonce_, abi.encodePacked(messageWithSender), commitmentLevel);

        unchecked {
            nonce = nonce_ + 1;
        }

        require(sentMessages[messageWithSender] == 0, "WormholeMessenger: has message");
        sentMessages[messageWithSender] = 1;

        emit MessageSent(messageWithSender, sequence);
    }

    function receiveMessage(bytes memory encodedMsg) external {
        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedMsg);

        require(valid, reason);
        require(vm.payload.length == 32, "WormholeMessenger: wrong length");

        bytes32 messageWithSender = bytes32(vm.payload);
        require(uint8(messageWithSender[1]) == chainId, "WormholeMessenger: wrong chainId");

        require(otherWormholeMessengers[vm.emitterChainId] == vm.emitterAddress, "WormholeMessenger: wrong emitter");

        receivedMessages[messageWithSender] = 1;

        emit MessageReceived(messageWithSender, vm.sequence);
    }

    function setCommitmentLevel(uint8 value) external onlyOwner {
        commitmentLevel = value;
    }

    function setOtherChainIds(bytes32 value) external onlyOwner {
        otherChainIds = value;
    }

    function registerWormholeMessenger(uint16 chainId_, bytes32 address_) external onlyOwner {
        otherWormholeMessengers[chainId_] = address_;
    }

    function withdrawGasTokens(uint amount) external onlyOwner {
        payable(msg.sender).transfer(amount);
    }

    fallback() external payable {
        revert("Unsupported");
    }

    receive() external payable {
        emit Received(msg.sender, msg.value);
    }
}
Configuraciones
{
  "compilationTarget": {
    "contracts/WormholeMessenger.sol": "WormholeMessenger"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"uint256","name":"chainId_","type":"uint256"},{"internalType":"bytes32","name":"otherChainIds_","type":"bytes32"},{"internalType":"contract IWormhole","name":"wormhole_","type":"address"},{"internalType":"uint8","name":"commitmentLevel_","type":"uint8"},{"internalType":"contract IGasOracle","name":"gasOracle_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"message","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"sequence","type":"uint64"}],"name":"MessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"message","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"sequence","type":"uint64"}],"name":"MessageSent","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":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"Received","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"gasUsage","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"getTransactionCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"otherChainIds","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedMsg","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"receivedMessages","outputs":[{"internalType":"uint256","name":"isReceived","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"bytes32","name":"address_","type":"bytes32"}],"name":"registerWormholeMessenger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"message","type":"bytes32"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"sentMessages","outputs":[{"internalType":"uint256","name":"isSent","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"value","type":"uint8"}],"name":"setCommitmentLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IGasOracle","name":"gasOracle_","type":"address"}],"name":"setGasOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"gasAmount","type":"uint256"}],"name":"setGasUsage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"value","type":"bytes32"}],"name":"setOtherChainIds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawGasTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]