title: 🪝 Hooks sidebarTitle: Hooks icon: fishing-rod description: 라이선스 토큰을 발행하거나 파생물을 등록하기 전에 사용자 정의 로직을 추가합니다. License Tokens 또는 파생물을 등록하기 전에.

훅에는 두 가지 유형이 있습니다:

  1. 라이선싱 훅: 라이선스 토큰을 발행하기 전에 사용자 정의 로직을 추가할 수 있습니다라이선스 토큰을 발행하기 전에 사용자 정의 로직을 추가 (그리고 파생물을 등록할 때도). 예를 들어, 동적 가격 요청, 발행할 수 있는 라이선스 토큰 수량 제한, 화이트리스트 등이 있습니다. 라이선싱 훅은 언제든지 라이선싱 구성에 추가/수정할 수 있습니다.
  2. 상업화 검사기 훅: 라이선싱 훅과 유사하지만, 라이선스 조건의 직접적인 부분이며 변경되지 않습니다. 또한 사용자 정의 발행 수수료를 반환할 수 없습니다.

라이선싱 훅

이는 ILicensingModule 인터페이스를 구현하는 계약으로, IHook에서 확장됩니다.ILicensingHook 인터페이스로, 이는 IModule에서 확장됩니다.

가장 중요한 것은, 라이선싱 훅이 beforeLicenseTransfer 함수를 구현한다는 것입니다. 이 함수는 라이선스 토큰이 발행되기 전에 호출되어 사용자 정의 로직을 구현하고 해당 라이선스 토큰의 최종 발행 수수료를 결정합니다.beforeMintLicenseTokens 함수로, 이는 License Token이 발행되기 전에 호출되어 사용자 정의 로직을 구현하고 최종 totalMintingFee을 결정하는 함수입니다.

ILicensingModule 스마트 계약을 보려면ILicensingHook 스마트 계약 여기를 클릭하세요.

ILicensingHook.sol
/// @notice This function is called when the LicensingModule mints license tokens.
/// @dev The hook can be used to implement various checks and determine the minting price.
/// The hook should revert if the minting is not allowed.
/// @param caller The address of the caller who calling the mintLicenseTokens() function.
/// @param licensorIpId The ID of licensor IP from which issue the license tokens.
/// @param licenseTemplate The address of the license template.
/// @param licenseTermsId The ID of the license terms within the license template,
/// which is used to mint license tokens.
/// @param amount The amount of license tokens to mint.
/// @param receiver The address of the receiver who receive the license tokens.
/// @param hookData The data to be used by the licensing hook.
/// @return totalMintingFee The total minting fee to be paid when minting amount of license tokens.
function beforeMintLicenseTokens(
  address caller,
  address licensorIpId,
  address licenseTemplate,
  uint256 licenseTermsId,
  uint256 amount,
  address receiver,
  bytes calldata hookData
) external returns (uint256 totalMintingFee);

이 함수가 mintingFee를 반환한다는 점에 주목하세요. “라이선스 조건에서 발행 수수료를 설정할 수 있고, LicensingModule에서도 설정할 수 있으며, beforeLicenseTransfer에서 동적 가격을 반환할 수도 있습니다. 실제 최종 발행 수수료는 어떻게 될까요?”라고 궁금해할 수 있습니다. 다음은 우선순위입니다:totalMintingFee. “라이선스 조건에서, LicenseConfig에서 발행 수수료를 설정할 수 있고, beforeMintLicenseTokens에서 동적 가격을 반환할 수 있습니다. 실제 최종 발행 수수료는 어떻게 될까요?”라고 궁금해할 수 있습니다. 여기 우선순위가 있습니다:

발행 수수료중요도
beforeLicenseTransfer에서 반환된 mintingFeetotalMintingFee에서 반환된 beforeMintLicenseTokens최우선 순위
LicensingModule에 설정된 mintingFeemintingFee에서 설정된 LicenseConfig⬇️
라이선스 조건에 설정된 mintingFeemintingFee 라이선스 조건에서 설정된최하위 순위

외부 라이선스 훅의 잠재적으로 악의적인 구현에 주의하세요. 선택한 훅의 코드를 먼저 확인하세요. Story 팀에 의해 검토되거나 감사되지 않았을 수 있습니다.

사용 가능한 훅

다음은 우리 프로토콜에 배포된 사용 가능한 훅들입니다.

이 훅들의 배포된 주소를 보려면 여기를 확인하세요.

설명계약 코드
LockLicenseHook라이선스 토큰의 발행 또는 새로운 파생물 등록을 중지합니다.여기에서 보기 ↗️
TotalLicenseTokenLimitHook발행할 수 있는 라이선스 토큰의 수량에 제한을 설정하며, 언제든지 업데이트 가능합니다.여기에서 보기 ↗️

훅 구현하기

라이선싱 훅은 궁극적으로 ILicensingHook 인터페이스를 구현하는 스마트 계약입니다. 인터페이스는 여기에서 볼 수 있습니다. 우리는 이미 몇 가지 라이선싱 훅을 배포했습니다 (위의 차트를 참조하세요).

라이선싱 훅을 실제로 사용하려면 라이선싱 구성에서 설정해야 합니다. 라이선싱 구성은 기본적으로 IP 자산에 조건을 첨부할 때 라이선스 조건에 설정하는 일련의 구성입니다.

1

라이선싱 구성 생성

먼저 라이선싱 구성을 생성해야 합니다:

import { LicensingConfig } from '@story-protocol/core-sdk';

const licensingConfig: LicensingConfig = {
    isSet: true,
    mintingFee: 0n,
    // address of TotalLicenseTokenLimitHook
    // from https://docs.story.foundation/developers/deployed-smart-contracts
    licensingHook: '0xaBAD364Bfa41230272b08f171E0Ca939bD600478',
    hookData: zeroAddress,
    commercialRevShare: 0,
    disabled: false,
    expectMinimumGroupRewardShare: 0,
    expectGroupRewardPool: zeroAddress,
}
2

라이선싱 구성 설정

다음으로, 라이선스 조건에 라이선싱 구성을 설정합니다. 다음 예시에서는 IP 자산을 등록할 때 이 작업이 이루어지는 것을 보여줍니다:

이 코드 스니펫은 약간의 설정이 필요하며, TypeScript SDK 설정 방법을 이미 이해하고 있는 개발자를 위한 것입니다. 더 자세히 알고 싶다면, 작동하는 코드 예시를 확인하세요.

이는 mintAndRegisterIpAssetWithPilTerms 메서드를 사용합니다. 여기에서 찾을 수 있습니다.

const response = await client.ipAsset.mintAndRegisterIpAssetWithPilTerms({
    spgNftContract: '0xc32A8a0FF3beDDDa58393d022aF433e78739FAbc', // public spg contract for ease-of-use
    licenseTermsData: [
        {
            terms: { defaultMintingFee: 0, commercialUse: true, ... }, // dummy license terms
            // set the licensing config here
            licensingConfig: licensingConfig
        },
    ],
    ipMetadata: {
        ipMetadataURI: 'test-uri',
        ipMetadataHash: toHex('test-metadata-hash', { size: 32 }),
        nftMetadataHash: toHex('test-nft-metadata-hash', { size: 32 }),
        nftMetadataURI: 'test-nft-uri',
    },
    txOptions: { waitForTransaction: true },
})
3

제한을 1로 설정

이제 우리의 조건에 라이선싱 구성을 설정했으므로, 훅의 setTotalLicenseTokenLimit 함수를 호출하여 발행할 수 있는 라이선스의 최대 수를 1로 설정할 수 있습니다.

이를 위한 Story SDK 메서드는 없으므로, viem의 writeContract 메서드를 사용해야 합니다.

import { totalLicenseTokenLimitHook } from './abi/totalLicenseTokenLimitHook'

const { request } = await publicClient.simulateContract({
    // address of TotalLicenseTokenLimitHook
    // from https://docs.story.foundation/developers/deployed-smart-contracts
    address: '0xaBAD364Bfa41230272b08f171E0Ca939bD600478',
    abi: totalLicenseTokenLimitHook,
    functionName: 'setTotalLicenseTokenLimit',
    args: [
        response.ipId, // ipId from the step above
        '0x2E896b0b2Fdb7457499B56AAaA4AE55BCB4Cd316', // the address of PILicenseTemplate from https://docs.story.foundation/developers/deployed-smart-contracts
        response.licenseTermsIds![0], // licenseTermsId
        1n, // limit (as BigInt)
    ],
    account: account, // Specify the account to use for permission checking
})

// Prepare transaction
const hash = await walletClient.writeContract({ ...request, account: account })

// Wait for transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({
    hash,
})

상업화 검사기 훅

문서가 곧 제공될 예정입니다. 그 동안 질문이 있다면 Builder’s Discord에서 문의해 주세요.