Create your own Hook & ISM
Hooks and ISMs have a complementary relationship: you can customize your behavior from origin and they use a pairwise ISM contract on the destination to verify your custom hook behavior.
You can implement and utilize your own hook and ISM pattern as per your requirements. You can use an external bridge provider like Wormhole or Chainlink’s CCIP by implementing the IPostDispatchHook
interface on the source chain and IInterchainSecurityModule
on the destination chain.
Hooks currently expect metadata to be formatted with the
StandardHookMetadata
library.
You can also inherit from our AbstractMessageIdAuthorizedIsm
which allows for access control for an intermediate verifyMessageId
function call which sets in storage the messageId to true if received from the authorized AbstractMessageIdAuthHook
hook. This pattern is used currently in the OpStackHook
<> OpStackIsm
pattern.
Workflow
Interface
After implementing the above interfaces, you can override default hook along the hook metadata by using the overloaded dispatch
call in our mailbox.
On the source chain:
mailbox.dispatch()
calls your custom hook viaAbstractMessageIdAuthHook.postDispatch()
._postDispatch
checks whetherlatestDispatchedId
is the id being dispatched from the hook to make the mailbox is the contract calling the hook (since callingpostDispatch
isn’t access controlled)_sendMessageId
calls your custom external bridge logic like calling the CCIP router contract.
On the destination chain:
- The external bridge will call
verifyMessageId
function (which is access-controlled) and sets themessageId
in theverifiedMessages
mapping to true. - On receiving the message for the relayer, the mailbox will call your ISM contract (specified in your recipient address) which checks if the messageId in the
verifiedMessages
mapping is true and returns true to the mailbox and vice versa.
AbstractMessageIdAuthorizedIsm
can send msg.value
through postDispatch
calls and we utilize the verifiedMessages
’ little endian 255 bits for
storing the msg.value
and the top bit for the actual receipt of the
messageId delivery. Therefore, you can send up to 2^255 amount of value of the
native token from origin and the destination ISM can only receive 2^255 amount
of value of native token on the destination chain.
Access Control
If postDispatch
must only be called with a message
that was just dispatched, the latestDispatchedId
function on the Mailbox can be used to verify the message was actually dispatched.
This is used instead of some require(mailbox == msg.sender)
to support
composition where a hook may pass a message
along to another hook.
The following utility is provided in the MailboxClient
library for convenience.