Hooks
Hooks are smart contracts that can be set on a Channel. A Hook defines the rules for commenting on the specified Channel. They unlock flexible and powerful behaviors, such as:
- Defining who can comment and how comments behave
- Charging a small fee to post a comment
- Integrating with other protocols, such as tokens or NFTs
Protocol Fee
For detailed information about protocol fees, including hook fees, see the Protocol Fees page.
Available hook Functions
onInitialize - Called when a channel is initialized
onCommentAdd - Called when a comment is added
onCommentEdit - Called when a comment is edited
onCommentDelete - Called when a comment is deleted
onChannelUpdate - Called when a channel is updated
onCommentHookDataUpdate - Called when hook metadata is updated for an existing comment
Discover community created hooks
Awesome hooks is a collection of hooks that can be used to build on top of ECP.
Modifying the hook on a channel
channelManager.setHook(channelId, hookAddress);Updating hook metadata
The updateCommentHookData function allows you to trigger a hook to update its metadata for an existing comment. This is useful for scenarios where hook metadata needs to be refreshed based on external conditions or time-based changes.
// Trigger hook metadata update for a specific comment
commentManager.updateCommentHookData(commentId);- Gas Efficient: Only updates specified metadata fields using SET and DELETE operations
- Explicit Operations: Hooks return precise operations instead of replacing all metadata
- Non-Payable: No ETH required for metadata updates
- Permission-Based: Only works if the channel's hook has
onCommentHookDataUpdate: true
function _onCommentHookDataUpdate(
Comments.Comment calldata commentData,
Metadata.MetadataEntry[] calldata metadata,
Metadata.MetadataEntry[] calldata hookMetadata,
address msgSender,
bytes32 commentId
) internal override returns (Comments.MetadataEntryOp[] memory) {
Comments.MetadataEntryOp[] memory operations = new Comments.MetadataEntryOp[](
2
);
// Update an existing field
operations[0] = Comments.MetadataEntryOp({
operation: Comments.MetadataOperation.SET,
key: "string score",
value: abi.encode(calculateNewScore(commentData))
});
// Delete a field
operations[1] = Comments.MetadataEntryOp({
operation: Comments.MetadataOperation.DELETE,
key: "string temp_data",
value: "" // Ignored for DELETE operations
});
return operations;
}Writing Your Own hooks
Hooks allow you to customize channel behavior. To create a custom hook:
- Inherit from BaseHook
- Override the desired hook functions
- Implement the required permissions
Basic hook example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { BaseHook } from "@ecp.eth/protocol/src/hooks/BaseHook.sol";
import { Hooks } from "@ecp.eth/protocol/src/types/Hooks.sol";
import { Comments } from "@ecp.eth/protocol/src/types/Comments.sol";
import { Channels } from "@ecp.eth/protocol/src/types/Channels.sol";
contract MyCustomHook is BaseHook {
function _getHookPermissions()
internal
pure
override
returns (Hooks.Permissions memory)
{
return
Hooks.Permissions({
onInitialize: true, // Enable channel initialization hook
onCommentAdd: true, // Enable comment addition hook
onCommentEdit: false, // Disable comment editing hook
onCommentDelete: false, // Disable comment deletion hook
onChannelUpdate: false, // Disable channel update hook
onCommentHookDataUpdate: false // Disable comment hook update hook
});
}
function _onInitialize(
address channelManager,
Channels.Channel memory channelData,
uint256 channelId,
Metadata.MetadataEntry[] calldata metadata
) internal override returns (bool) {
// Your initialization logic here
return true;
}
function _onCommentAdd(
Comments.Comment calldata commentData,
address msgSender,
bytes32 commentId
) internal override returns (string memory) {
// Your comment addition logic here
return "";
}
}Best Practices
-
Hook Implementation
- Keep hook logic gas-efficient
- Handle errors gracefully
- Validate inputs thoroughly
-
Channel Management
- Use meaningful channel names and descriptions
- Keep track of channel IDs
-
Security
- Validate all inputs in hooks
- Be cautious with external calls
- Test hooks thoroughly
- Consider implementing a ReentrancyGuard in your hook if you want to prevent reentrancy attacks
-
Fees
- Consider refunding any excess fees to the user
- use
channelManager.calculateMsgValueWithHookFeeto calculate the correct amount of ETH to send to your hook
Troubleshooting
-
Hook Not Working
- Check if hook permissions are set correctly
- Verify the hook implementation
- Ensure the hook is properly set on the channel
- Remember that hooks are called after modifying contract state, and any revert in a hook will revert the entire transaction
-
Channel Creation Fails
- Ensure you have enough ETH for the creation fee
- Check if the channel name/description is valid
- Verify that metadata is valid JSON
- Verify the hook is approved by the ECP team
-
Hook Reverts
- Check the hook implementation for errors
- Verify input validation
- Check gas limits