Skip to content

Instantly share code, notes, and snippets.

@dbeal-eth
Created December 16, 2021 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dbeal-eth/5f88d0f51d49cc0fc12389227f84ca1a to your computer and use it in GitHub Desktop.
Save dbeal-eth/5f88d0f51d49cc0fc12389227f84ca1a to your computer and use it in GitHub Desktop.
theoretically cross chain messaging implementation
pragma solidity ^0.5.16;
// Inheritance
import "./Owned.sol";
import "./interfaces/IAddressResolver.sol";
import "./interfaces/ISystemMessenger.sol";
// https://docs.synthetix.io/contracts/source/contracts/systemstatus
contract SystemMessenger is Owned, ISystemMessenger {
bytes32 public constant CONTRACT_NAME = "SystemMessenger";
IAddressResolver public resolver;
uint[] public activeChains;
mapping(uint => address) public messengerAddresses;
mapping(uint => uint) public outgoingNonces;
mapping(uint => uint) public incomingNonces;
constructor(address _owner, IAddressResolver _resolver) public Owned(_owner) {
resolver = _resolver;
}
/* ========== VIEWS ========== */
/* ========== MUTATIVE FUNCTIONS ========== */
// send a message only to one chain
function post(
uint targetChainId,
bytes32 targetContract,
bytes data,
uint32 gasLimit
) public onlyAuthorizedMessenger {
emit MessagePosted(targetChainId, outgoingNonces[targetChainId]++, targetContract, data, gasLimit);
}
// sends a copy of this message to all chains synthetix is deployed to
function broadcast(
bytes32 targetContract,
bytes data,
uint32 gasLimit
) public onlyAuthorizedMessenger {
for (uint i = 0;i < activeChains.length;i++) {
post(activeChains[i], targetContract, data, gasLimit);
}
}
function receive(
uint srcChainId,
uint srcNonce,
bytes32 targetContract,
bytes data,
uint32 gasLimit
) external onlyRelayer {
require(incomingNonces[srcChainId]++ == srcNonce, "can only submit next message nonce");
address target = resolver.requireAndGetAddress(targetContract, "Target address resolver contract does not exist");
target.call{gas:gasLimit}(data);
}
function addChain(uint chainId, address messenger) external onlyOwnerOrSelf {
broadcast("SystemMessenger", abi.encodeWithSelector("", chainId, messenger), msg.gas);
messengerAddresses[chainId] = messenger;
activeChains.push(chainId);
}
function addChain(uint chainId, address messenger) external onlyOwnerOrSelf {
broadcast("SystemMessenger", abi.encodeWithSelector("", chainId, messenger), msg.gas);
messengerAddresses[chainId] = address(0);
for (uint i = 0;i < activeChains.length;i++) {
if (activeChains[i] == chainId) {
activeChains[i] = activeChains[activeChains.length - 1];
activeChains.pop();
return;
}
}
revert("could not find specified chain id");
}
/* ========== EVENTS ========== */
event MessagePosted(uint indexed targetChainId, uint indexed nonce, bytes32 indexed targetContract, bytes data, uint32 gasLimit);
event MessageProcessed(bytes32 indexed srcChainId, uint indexed nonce, bytes32 indexed targetContract, bytes data, uint32 gasLimit);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment