--- title: 'Telepathy Validator for OmniBridge' --- Telepathy Validator for OmniBridge === [TOC] ## Introduction The [Telepathy Protocol](https://www.telepathy.xyz/) has been [launched](https://twitter.com/SuccinctLabs/status/1636429568172228609), which removes the need to trust centralized actors or permissioned multisigs when passing information between chains. For developers wishing to use Telepathy for cross-chain messaging, the standard path is to plug into the [Telepathy Router](https://docs.telepathy.xyz/protocol/contracts#router) by using the send function: ```Solidity send(uint32 destinationChainId, bytes32 destinationAddress, bytes calldata data) ``` For *existing* contracts that are cannot be modified to make this external call, Telepathy provides a different system: **On-Chain PubSub for events**. Since the [TokenBridge contracts](https://github.com/omni/tokenbridge-contracts) fall into the category, we will demonstrate how this system is used to create a Validator secured by the [Telepathy Light Client](https://docs.telepathy.xyz/protocol/contracts#light-client): ![gnosis-validator](https://i.imgur.com/Be6IAg7.png) For additional information on the protocol, please refer to the official [Telepathy docs](https://docs.telepathy.xyz/). This specific document will focus on the PubSub system and the Validator. Telepathy PubSub Technical Walkthrough --- To listen to any arbitrary event that was emitted on-chain, a contract must first [subscribe](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/src/pubsub/interfaces/IPubSub.sol#L45-L52) to it: ```Solidity function subscribe( uint32 sourceChainId, address sourceAddress, address callbackAddress, bytes32 eventSig, uint64 startSlot, uint64 endSlot ) external returns (bytes32 subscriptionId) ``` Then, the subscribed contract specified by `callbackAddress` will receive updates from the [publisher](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/src/pubsub/TelepathyPublisher.sol#L16) whenever a new event is emitted for that `sourceChainId` + `sourceAddress` + `eventSig`. All events that are published are verified with the Light Client and event proof in [publishEvent()](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/src/pubsub/TelepathyPublisher.sol#L26). The subscribed contract *must* implement [ISubscriptionReceiver](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/src/pubsub/interfaces/ISubscriptionReceiver.sol#L3). We also provide an abstract contract, [SubscriptionReceiver](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/src/pubsub/interfaces/SubscriptionReceiver.sol#L6), for ensuring that all the checks for handling this event are met. This means that all that needs to be done is implementing this function: ```Solidity function handlePublishImpl( bytes32 _subscriptionId, uint32 _sourceChainId, address _sourceAddress, uint64 _slot, bytes32[] memory _eventTopics, bytes memory _eventdata ) internal virtual; ``` Gnosis Validator Technical Walkthrough --- To create a trustless ETH->Gnosis Validator on top of this system, we simply subscribe to the [UserRequestForAffirmation](https://github.com/succinctlabs/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/upgradeable_contracts/arbitrary_message/ForeignAMB.sol#L6) event emitted by the [ForeignAMB](https://github.com/succinctlabs/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/upgradeable_contracts/arbitrary_message/ForeignAMB.sol#L5): ```Solidity event UserRequestForAffirmation(bytes32 indexed messageId, bytes encodedData); ``` In the [Telepathy Validator](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/examples/pubsub/gnosis/TelepathyValidator.sol#L11) contract deployed on Gnosis, we specify the Ethereum ForeignAMB and the event via its signature: ```Solidity bytes32 constant AFFIRMATION_EVENT_SIG = keccak256("UserRequestForAffirmation(bytes32,bytes)"); function subscribeToAffirmationEvent() external onlyOwner returns (bytes32) { subscriptionId = telepathyPubSub.subscribe( EVENT_SOURCE_CHAIN_ID, EVENT_SOURCE_ADDRESS, address(this), AFFIRMATION_EVENT_SIG, START_SLOT, END_SLOT ); return subscriptionId; } ``` The contract now receives updates whenever this event is emitted. It handles these in the [handlePublishImpl](https://github.com/succinctlabs/telepathy-contracts/blob/9ed099dc2eed7a000b2b3d5309da8ccf813a896d/examples/pubsub/gnosis/TelepathyValidator.sol#L67) function, where additional validation is done: ```Solidity function handlePublishImpl( bytes32 _subscriptionId, uint32 _sourceChainId, address _sourceAddress, uint64 _slot, bytes32[] memory eventTopics, bytes memory eventdata ) internal override { if (_sourceChainId != EVENT_SOURCE_CHAIN_ID) { revert InvalidSourceChain(_sourceChainId); } if (_sourceAddress != EVENT_SOURCE_ADDRESS) { revert InvalidSourceAddress(_sourceAddress); } if (_slot < START_SLOT || (END_SLOT != 0 && _slot > END_SLOT)) { revert InvalidSlot(_slot); } if (_subscriptionId != subscriptionId) { revert InvalidSubscriptionId(_subscriptionId); } (bytes memory header, bytes memory data) = abi.decode(eventdata, (bytes, bytes)); if (executeAffirmationsEnabled) { HOME_AMB.executeAffirmation(data); } emit AffirmationHandled(eventTopics[1], header, data); } ``` When this contract is added as a Validator, `executeAffirmationsEnabled` can be set to true and the HomeAMB's [executeAffirmation()](https://github.com/succinctlabs/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/upgradeable_contracts/arbitrary_message/BasicHomeAMB.sol#L20) function. For now, we emit `AffirmationHandled` with the event data. Results --- The Telepathy Validator contract is deployed, and the source code can be viewed on GnosisScan [here](https://gnosisscan.io/address/0xbfe15ccbf28c504ddcebcef60753abfff731a675#code). As shown in the [events](https://gnosisscan.io/address/0xbfe15ccbf28c504ddcebcef60753abfff731a675#events) tab, we can see these results successfully handled: ![https://gnosisscan.io/address/0xbfe15ccbf28c504ddcebcef60753abfff731a675#events](https://i.imgur.com/TrTsoPw.png) You can also find this and the PubSub system in our [contracts repository](https://github.com/succinctlabs/telepathy-contracts) on GitHub. Next Steps --- The Telepathy Validator contract needs to be added as one of the validators. Its address is: [0xbFe15ccbF28C504DdCEBCEf60753Abfff731a675](https://gnosisscan.io/address/0xbfe15ccbf28c504ddcebcef60753abfff731a675) Once the reliability and liveness has been demonstrated, it can then act as a *required* validator for all messages.