LSP1 Tip-on-Follow Delegate
LSP1 Universal Receiver Delegate that automatically tips LSP7 tokens to every new follower. Zero user interaction needed after setup — the UP handles it via the LSP26 follow notification.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {ILSP1UniversalReceiver} from "@lukso/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol";
import {ILSP7DigitalAsset} from "@lukso/lsp7-contracts/contracts/ILSP7DigitalAsset.sol";
/// @dev LSP26 follow notification typeId
bytes32 constant _TYPEID_LSP26_FOLLOW =
0x71e02f9f05bcd5816ec4f3134aa2e5a916669537000000000000000000000000;
/// @dev LSP26 Follower Registry on LUKSO Mainnet
address constant LSP26_FOLLOWER_REGISTRY = 0xf01103E5a9909Fc0DBe8166dA7085e0285daDDcA;
/**
* @title TipOnFollowDelegate
* @notice Auto-tip LSP7 tokens to every new follower via LSP1.
*
* SETUP on your Universal Profile:
* 1. Set LSP1UniversalReceiverDelegate:<followTypeId> = address(this)
* 2. Authorize this contract as LSP7 operator for your tip budget
*/
contract TipOnFollowDelegate is ILSP1UniversalReceiver {
ILSP7DigitalAsset public immutable tipToken;
uint256 public immutable tipAmount;
event TipSent(address indexed universalProfile, address indexed follower, uint256 amount);
event TipFailed(address indexed universalProfile, address indexed follower, string reason);
constructor(address _tipToken, uint256 _tipAmount) {
tipToken = ILSP7DigitalAsset(_tipToken);
tipAmount = _tipAmount;
}
function universalReceiver(
bytes32 typeId,
bytes calldata data
) external override returns (bytes memory) {
if (typeId != _TYPEID_LSP26_FOLLOW) return "";
if (msg.sender != LSP26_FOLLOWER_REGISTRY) return "";
if (data.length < 20) return "";
address follower = address(bytes20(data[data.length - 20:]));
address universalProfile = tx.origin;
try tipToken.transfer(universalProfile, follower, tipAmount, true, "") {
emit TipSent(universalProfile, follower, tipAmount);
} catch Error(string memory reason) {
emit TipFailed(universalProfile, follower, reason);
} catch {
emit TipFailed(universalProfile, follower, "unknown error");
}
return "";
}
}