Last active
November 1, 2023 09:55
-
-
Save zengzengzenghuy/2bcd1ecc04efd5ff317f753fc246e2a9 to your computer and use it in GitHub Desktop.
YahoMessageDispatcher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: LGPL-3.0-only | |
pragma solidity ^0.8.17; | |
interface IHashiExecutor { | |
function onMessage(bytes data, bytes32 messageId, uint256 fromChainId, address from); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: LGPL-3.0-only | |
pragma solidity ^0.8.17; | |
struct Message { | |
address to; | |
address from; | |
uint256 toChainId; | |
uint256 fromChainId; | |
bytes data; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: LGPL-3.0-only | |
pragma solidity ^0.8.17; | |
interface IMessageExecutor { | |
error MessageIdAlreadyExecuted(bytes32 messageId); | |
error MessageFailure(bytes32 messageId,bytes errorData); | |
event MessageIdExecuted(uint256 indexed fromChainId, bytes32 indexed messageId); | |
function onMessage(bytes data, bytes32 messageId, uint256 fromChainId, address from); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: LGPL-3.0-only | |
pragma solidity ^0.8.17; | |
import { IMessageRelay } from "./interfaces/IMessageRelay.sol"; | |
import { IMessageDispatcher, Message } from "./interfaces/IMessageDispatcher.sol"; | |
import { MessageHashCalculator } from "./utils/MessageHashCalculator.sol"; | |
contract Yaho is IMessageDispatcher, MessageHashCalculator { | |
mapping(uint256 => bytes32) public hashes; | |
uint256 private count; | |
error NoMessagesGiven(address emitter); | |
error NoMessageIdsGiven(address emitter); | |
error NoAdaptersGiven(address emitter); | |
error UnequalArrayLengths(address emitter); | |
/// @dev Dispatches a batch of messages, putting their into storage and emitting their contents as an event. | |
/// @param messages An array of Messages to be dispatched. | |
/// @return messageIds An array of message IDs corresponding to the dispatched messages. | |
function dispatchMessages(Message[] memory messages) public payable returns (bytes32[] memory) { | |
if (messages.length == 0) revert NoMessagesGiven(address(this)); | |
bytes32[] memory messageIds = new bytes32[](messages.length); | |
for (uint256 i = 0; i < messages.length; i++) { | |
bytes32 id = keccak256(bytes.concat(bytes32(count),bytes32(block.chainid))); | |
hashes[id] = calculateHash(block.chainid, id, address(this), msg.sender, messages[i]); | |
messageIds[i] = id; | |
emit MessageDispatched(id, msg.sender, messages[i].toChainId, messages[i].to, messages[i].data); | |
count++; | |
} | |
return messageIds; | |
} | |
/// @dev Relays hashes of the given messageIds to the given adapters. | |
/// @param messageIds Array of IDs of the message hashes to relay to the given adapters. | |
/// @param adapters Array of relay adapter addresses to which hashes should be relayed. | |
/// @param destinationAdapters Array of oracle adapter addresses to receive hashes. | |
/// @return adapterReciepts Reciepts from each of the relay adapters. | |
function relayMessagesToAdapters( | |
uint256[] memory messageIds, | |
address[] memory adapters, | |
address[] memory destinationAdapters, | |
uint256 gas | |
) external payable returns (bytes32[] memory) { | |
if (messageIds.length == 0) revert NoMessageIdsGiven(address(this)); | |
if (adapters.length == 0) revert NoAdaptersGiven(address(this)); | |
if (adapters.length != destinationAdapters.length) revert UnequalArrayLengths(address(this)); | |
bytes32[] memory adapterReciepts = new bytes32[](adapters.length); | |
for (uint256 i = 0; i < adapters.length; i++) { | |
adapterReciepts[i] = IMessageRelay(adapters[i]).relayMessages(messageIds, destinationAdapters[i], gas); | |
} | |
return adapterReciepts; | |
} | |
/// @dev Dispatches an array of messages and relays their hashes to an array of relay adapters. | |
/// @param messages An array of Messages to be dispatched. | |
/// @param adapters Array of relay adapter addresses to which hashes should be relayed. | |
/// @param destinationAdapters Array of oracle adapter addresses to receive hashes. | |
/// @return messageIds An array of message IDs corresponding to the dispatched messages. | |
/// @return adapterReciepts Reciepts from each of the relay adapters. | |
function dispatchMessagesToAdapters( | |
Message[] memory messages, | |
address[] memory adapters, | |
address[] memory destinationAdapters, | |
uint256 gas | |
) external payable returns (bytes32[] memory messageIds, bytes32[] memory) { | |
if (adapters.length == 0) revert NoAdaptersGiven(address(this)); | |
messageIds = dispatchMessages(messages); | |
uint256[] memory uintIds = new uint256[](messageIds.length); | |
for (uint256 i = 0; i < messageIds.length; i++) { | |
uintIds[i] = uint256(messageIds[i]); | |
} | |
bytes32[] memory adapterReciepts = new bytes32[](adapters.length); | |
for (uint256 i = 0; i < adapters.length; i++) { | |
adapterReciepts[i] = IMessageRelay(adapters[i]).relayMessages(uintIds, destinationAdapters[i], gas); | |
} | |
return (messageIds, adapterReciepts); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: LGPL-3.0-only | |
pragma solidity ^0.8.17; | |
import { IHashi, IOracleAdapter } from "./interfaces/IHashi.sol"; | |
import { Message } from "./interfaces/IMessage.sol"; | |
import { IMessageExecutor } from "./interfaces/IMessageExecutor.sol"; | |
import { MessageHashCalculator } from "./utils/MessageHashCalculator.sol"; | |
contract Yaru is IMessageExecutor, MessageHashCalculator { | |
IHashi public immutable hashi; | |
address public immutable yaho; | |
uint256 public immutable chainId; | |
mapping(bytes32 => bool) public executed; | |
address public sender; | |
error ReentranceNotAllowed(address); | |
error UnequalArrayLengths(address emitter); | |
error InvalidSender(address emitter, address sender); | |
error HashMismatch(address emitter, uint256 id, bytes32 reportedHash, bytes32 calculatedHash); | |
/// @param _hashi Address of the Hashi contract. | |
/// @param _yaho Address of the Yaho contract | |
constructor(IHashi _hashi, address _yaho, uint256 _chainId) { | |
hashi = _hashi; | |
yaho = _yaho; | |
chainId = _chainId; | |
} | |
/// @dev Executes messages validated by a given set of oracle adapters | |
/// @param messages Array of messages to execute. | |
/// @param messageIds Array of corresponding messageIds to query for hashes from the given oracle adapters. | |
/// @param senders Array of addresses that sent the corresponding messages. | |
/// @param oracleAdapters Array of oracle adapters to query. | |
/// @return returnDatas Array of data returned from each executed message. | |
function executeMessages( | |
Message[] memory messages, | |
uint256[] memory messageIds, | |
address[] memory senders, | |
IOracleAdapter[] memory oracleAdapters | |
) public returns (bytes[] memory) { | |
if (sender != address(0)) revert ReentranceNotAllowed(address(0)); | |
if (messages.length != senders.length || messages.length != messageIds.length) | |
revert UnequalArrayLengths(address(this)); | |
bytes[] memory returnDatas = new bytes[](messages.length); | |
for (uint256 i = 0; i < messages.length; i++) { | |
bytes32 id = messageIds[i]; | |
if (executed[id]) revert MessageIdAlreadyExecuted(id); | |
if (senders[i] == address(0)) revert InvalidSender(address(this), senders[i]); | |
executed[id] = true; | |
Message memory message = messages[i]; | |
sender = senders[i]; | |
bytes32 reportedHash = hashi.getHash(chainId, id, oracleAdapters); | |
bytes32 calculatedHash = calculateHash(chainId, id, yaho, sender, message); | |
if (reportedHash != calculatedHash) revert HashMismatch(address(this), id, reportedHash, calculatedHash); | |
(bool success, bytes memory returnData) = (message.to).call(message.data); | |
if (!success) revert MessageFailure(id, bytes("Message call Failed"); | |
delete sender; | |
returnDatas[i] = returnData; | |
emit MessageIdExecuted(message.fromChainId, bytes32(id)); | |
} | |
return returnDatas; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment