The Telepathy Protocol has been launched, 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 by using the send function:
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 fall into the category, we will demonstrate how this system is used to create a Validator secured by the Telepathy Light Client:
For additional information on the protocol, please refer to the official Telepathy docs. This specific document will focus on the PubSub system and the Validator.
To listen to any arbitrary event that was emitted on-chain, a contract must first subscribe to it:
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 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().
The subscribed contract must implement ISubscriptionReceiver. We also provide an abstract contract, SubscriptionReceiver, 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:
function handlePublishImpl(
bytes32 _subscriptionId,
uint32 _sourceChainId,
address _sourceAddress,
uint64 _slot,
bytes32[] memory _eventTopics,
bytes memory _eventdata
) internal virtual;
To create a trustless ETH->Gnosis Validator on top of this system, we simply subscribe to the UserRequestForAffirmation event emitted by the ForeignAMB:
event UserRequestForAffirmation(bytes32 indexed messageId, bytes encodedData);
In the Telepathy Validator contract deployed on Gnosis, we specify the Ethereum ForeignAMB and the event via its signature:
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 function, where additional validation is done:
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() function.
For now, we emit AffirmationHandled
with the event data.
The Telepathy Validator contract is deployed, and the source code can be viewed on GnosisScan here. As shown in the events tab, we can see these results successfully handled:
You can also find this and the PubSub system in our contracts repository on GitHub.
The Telepathy Validator contract needs to be added as one of the validators. Its address is: 0xbFe15ccbF28C504DdCEBCEf60753Abfff731a675
Once the reliability and liveness has been demonstrated, it can then act as a required validator for all messages.