Hooks๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ์๋ License Tokens ๋ฐํ ๋๋ ํ์๋ฌผ ๋ฑ๋ก ์ ์ฌ์ฉ์ ์ ์ ๊ตฌํ, ์ ํ ๋ฐ ๊ธฐ๋ฅ์ ๋ง๋ค ์ ์์ต๋๋ค.
Hooks์๋ ๋ ๊ฐ์ง ์ ํ์ด ์์ต๋๋ค:
Licensing Hooks : ๋ผ์ด์ ์ค ํ ํฐ์ ๋ฐํํ๊ธฐ ์ ์ ์ฌ์ฉ์ ์ ์ ๋ก์ง์ ์ถ๊ฐ ํ ์ ์๊ฒ ํด์ค๋๋ค(๋ฐ ํ์๋ฌผ ๋ฑ๋ก). ์๋ฅผ ๋ค์ด, ๋์ ๊ฐ๊ฒฉ ์์ฒญ, ๋ฐํ ๊ฐ๋ฅํ ๋ผ์ด์ ์ค ํ ํฐ ์ ์ ํ, ํ์ดํธ๋ฆฌ์คํธ ๋ฑ์ด ์์ต๋๋ค. Licensing Hooks๋ ์ธ์ ๋ ์ง licensing config์์ ์ถ๊ฐ/์์ ํ ์ ์์ต๋๋ค.
Commercializer Checker Hooks : Licensing Hooks์ ์ ์ฌํ์ง๋ง, ์ง์ ์ ์ผ๋ก ๋ผ์ด์ ์ค ์กฐ๊ฑด์ ์ผ๋ถ์ด๋ฉฐ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ๋ํ ์ฌ์ฉ์ ์ ์ ๋ฐํ ์์๋ฃ๋ฅผ ๋ฐํํ ์๋ ์์ต๋๋ค.
Licensing Hooks
์ด๋ค์ IModule์ ํ์ฅํ๋ ILicensingHook ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ์ปจํธ๋ํธ์
๋๋ค.
๊ฐ์ฅ ์ค์ํ ์ ์, Licensing Hook๊ฐ License Token์ด ๋ฐํ๋๊ธฐ ์ ์ ํธ์ถ๋์ด ์ฌ์ฉ์ ์ ์ ๋ก์ง ์ ๊ตฌํํ๊ณ ํด๋น License Token์ ์ต์ข
totalMintingFee๋ฅผ ๊ฒฐ์ ํ๋ beforeMintLicenseTokens ํจ์๋ฅผ ๊ตฌํํ๋ค๋ ์ ์
๋๋ค.
ILicensingHook ์ค๋งํธ ์ปจํธ๋ํธ๋
์ฌ๊ธฐ ์์ ํ์ธํ์ธ์.
/// @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 );
์ด ํจ์๊ฐ totalMintingFee๋ฅผ ๋ฐํํ๋ค๋ ์ ์ ์ ์ํ์ธ์. โLicense Terms์์ ๋ฐํ ์์๋ฃ๋ฅผ ์ค์ ํ ์๋ ์๊ณ , LicenseConfig์์๋ ์ค์ ํ ์ ์๊ณ , beforeMintLicenseTokens์์ ๋์ ๊ฐ๊ฒฉ์ ๋ฐํํ ์๋ ์๋ค. ๊ทธ๋ฌ๋ฉด ์ต์ข
๋ฐํ ์์๋ฃ๋ ์ค์ ๋ก ๋ฌด์์ด ๋ ๊น?โ๋ผ๊ณ ๊ถ๊ธํดํ ์ ์์ต๋๋ค. ์ฐ์ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
๋ฐํ ์์๋ฃ ์ค์๋ beforeMintLicenseTokens์์ ๋ฐํ๋ totalMintingFee์ต๊ณ ์ฐ์ ์์ LicenseConfig์ ์ค์ ๋ mintingFeeโฌ๏ธ License Terms์ ์ค์ ๋ mintingFee ์ต์ ์ฐ์ ์์
์ธ๋ถ license hook์ ์ ์ฌ์ ์ผ๋ก ์
์์ ์ธ ๊ตฌํ์ ์ฃผ์ํ์ธ์.
์ ํํ hook์ ์ฝ๋๋ DATA Foundation ํ์ ์ํด ๊ฒํ ๋๋ ๊ฐ์ฌ๋์ง ์์์ ์
์์ผ๋ฏ๋ก ๋จผ์ ์ง์ ํ์ธํ์ธ์.
์ฌ์ฉ ๊ฐ๋ฅํ Hooks
๋ค์์ ์ฐ๋ฆฌ ํ๋กํ ์ฝ์ ๋ฐฐํฌ๋์ด ์ฌ์ฉํ ์ ์๋ hooks์
๋๋ค.
์ด hooks์ ๋ฐฐํฌ๋ ์ฃผ์๋ ์ฌ๊ธฐ ์์ ํ์ธํ์ธ์.
Hook ์ค๋ช
์ปจํธ๋ํธ ์ฝ๋ LockLicenseHook ๋ผ์ด์ ์ค ํ ํฐ ๋ฐํ ๋๋ ์๋ก์ด ํ์๋ฌผ ๋ฑ๋ก์ ์ค๋จํฉ๋๋ค. ์ฌ๊ธฐ ๋ณด๊ธฐ โ๏ธ TotalLicenseTokenLimitHook ๋ฐํ ๊ฐ๋ฅํ ๋ผ์ด์ ์ค ํ ํฐ์ ์์ ์ ํ์ ์ค์ ํ๋ฉฐ, ์ธ์ ๋ ์ง ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ ๋ณด๊ธฐ โ๏ธ
Hooks ๊ตฌํํ๊ธฐ
SDK ์ฝ๋ ์์ licensing hook๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ์ค์ ์๋ํ๋ TypeScript SDK ์ฝ๋ ์์ .
๋ ๊ตฌ์ฒด์ ์ผ๋ก, ๋ฐํ ๊ฐ๋ฅํ ๋ผ์ด์ ์ค ์๋ฅผ ์ ํํ๋ ๋ฐฉ๋ฒ.
Solidity ์ฝ๋ ์์ licensing hook๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ์ค์ ์๋ํ๋ Solidity ์ฝ๋ ์์ .
๋ ๊ตฌ์ฒด์ ์ผ๋ก, ๋ฐํ ๊ฐ๋ฅํ ๋ผ์ด์ ์ค ์๋ฅผ ์ ํํ๋ ๋ฐฉ๋ฒ.
Licensing Hooks๋ ๊ถ๊ทน์ ์ผ๋ก ILicensingHook ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ์ค๋งํธ ์ปจํธ๋ํธ์
๋๋ค. ์ธํฐํ์ด์ค๋ ์ฌ๊ธฐ ์์ ๋ณผ ์ ์์ต๋๋ค. ์ด๋ฏธ ๋ฐฐํฌ๋ ๋ช ๊ฐ์ง Licensing Hooks๊ฐ ์์ต๋๋ค(์ ์ฐจํธ ์ฐธ์กฐ).
์ค์ ๋ก Licensing Hook๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Licensing Config์ ์ค์ ํด์ผ ํฉ๋๋ค. Licensing Config๋ IP Asset์ ์กฐ๊ฑด์ ์ฒจ๋ถํ ๋ License Terms์ ์ค์ ํ๋ ์ผ๋ จ์ ๊ตฌ์ฑ์
๋๋ค.
Licensing Config ์์ฑ
๋จผ์ Licensing Config๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค: import { LicensingConfig } from '@story-protocol/core-sdk' ;
const licensingConfig : LicensingConfig = {
isSet: true ,
mintingFee: 0 n ,
// address of TotalLicenseTokenLimitHook
// from https://docs.datafdn.org/developers/deployed-smart-contracts
licensingHook: '0xaBAD364Bfa41230272b08f171E0Ca939bD600478' ,
hookData: zeroAddress ,
commercialRevShare: 0 ,
disabled: false ,
expectMinimumGroupRewardShare: 0 ,
expectGroupRewardPool: zeroAddress ,
}
Licensing Config ์ค์
๋ค์์ผ๋ก, License Terms์ Licensing Config๋ฅผ ์ค์ ํฉ๋๋ค. ๋ค์ ์์์์๋ IP Asset์ ๋ฑ๋กํ ๋ ์ด๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฝ๋๋ค: ์ด ์ฝ๋ ์ค๋ํซ์ ์ฝ๊ฐ์ ์ค์ ์ด ํ์ํ๋ฉฐ, ์ด๋ฏธ TypeScript SDK๋ฅผ ์ค์ ํ๋ ๋ฐฉ๋ฒ์
์ดํดํ๊ณ ์๋ ๊ฐ๋ฐ์๋ฅผ ์ํ ๊ฒ์
๋๋ค. ์์ธํ ๋ด์ฉ์ ์ค์ ์๋ํ๋ ์ฝ๋
์์ ๋ฅผ ํ์ธํ์ธ์. ์ด๋ ์ฌ๊ธฐ ์์ ์ฐพ์ ์ ์๋ registerIpAsset ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. const response = await client . ipAsset . registerIpAsset ({
nft: {
type: 'mint' ,
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' ,
}
})
console . log ( `Token ID: ${ response . tokenId } , IPA ID: ${ response . ipId } , License Terms ID: ${ response . licenseTermsIds } ` );
์ ํ์ 1๋ก ์ค์
์ด์ ์กฐ๊ฑด์ Licensing Config๋ฅผ ์ค์ ํ์ผ๋ฏ๋ก, hook์ setTotalLicenseTokenLimit ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ฐํ ๊ฐ๋ฅํ ์ต๋ ๋ผ์ด์ ์ค ์๋ฅผ 1๋ก ์ค์ ํ ์ ์์ต๋๋ค. const hookResponse = await client . license . setMaxLicenseTokens ({
ipId: response . ipId ,
licenseTermsId: response . licenseTermsIds ! [ 0 ],
maxLicenseTokens: 1000 ,
});
console . log ( `Max license tokens set at transaction hash ${ hookResponse . txHash } ` );
์๋ก์ด Licensing Hook ์์ฑ
์๋ก์ด licensing hook๋ฅผ ๋ง๋ค๊ณ DATA Foundation ํ๋กํ ์ฝ์ ํ์ดํธ๋ฆฌ์คํธ๋ก ๋ฑ๋กํ๋ ค๋ฉด ์๋ ์ ์ฐจ๋ฅผ ๋ฐ๋ฅด์ธ์.
Hook ๊ฐ๋ฐ : ์ด ํ
ํ๋ฆฟ ์ ์ฅ์ ๋ฅผ ํฌํฌํ์ฌ ๊ฐ๋ฐ์ ๋ถํธ์คํธ๋ฉํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ Aeneid ํ๋กํ ์ฝ์ ๋ํ ํ
์คํธ์ ํจ๊ป ์์ hook๊ฐ ํฌํจ๋์ด ์์ง๋ง, ์ฌ์ฉ์ ์ ํ ์ฌํญ์
๋๋ค.
Registered Modules ์ ์ฅ์ ํฌํฌ : registered-modules ์ ์ฅ์ ๋ฅผ ์์ ์ GitHub ๊ณ์ ์ผ๋ก ํฌํฌํ์ธ์.
Module ๋ชฉ๋ก ์
๋ฐ์ดํธ : registered-modules ์ ์ฅ์์์ hook-modules.json ํ์ผ์ hook์ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถ๊ฐํ์ธ์. aeneid ๋ฐ mainnet ๋ชจ๋์ hook๋ฅผ ๋ฐฐํฌ ๋ฐ ๋ธ๋ก ์ต์คํ๋ก๋ฌ์์ ๊ฒ์ฆ ํด์ผ ํฉ๋๋ค. ๋ค์ JSON ๊ตฌ์กฐ๋ฅผ ์ค์ํ๋์ง ํ์ธํ์ธ์:
{
"name" : "YourModuleName" ,
"aeneid" : {
"address" : "YourModuleAddress" ,
"blockExplorerLink" : "YourModuleBlockExplorerLink"
},
"mainnet" : {
"address" : "YourModuleAddress" ,
"blockExplorerLink" : "YourModuleBlockExplorerLink"
}
}
YourModuleName, YourModuleAddress, YourModuleBlockExplorerLink๋ฅผ ๊ฐ๊ฐ hook์ ์ด๋ฆ, ์ฃผ์, ๋ธ๋ก ์ต์คํ๋ก๋ฌ ํ์ด์ง ๋งํฌ๋ก ๋ฐ๊พธ์ธ์.
์์:
{
"name" : "LicenseCallerWhitelistHook" ,
"aeneid" : {
"address" : "0x37be56d9fb06d885cda3cb010096c94c28b4d658" ,
"blockExplorerLink" : "https://aeneid.datanetscan.io/address/0x37be56d9fb06d885cda3cb010096c94c28b4d658?tab=contract"
},
"mainnet" : {
"address" : "0x6d9d51a444c8318e8840e75dab7ed81b5a714610" ,
"blockExplorerLink" : "https://www.datanetscan.io/address/0x6d9d51a444c8318e8840e75dab7ed81b5a714610?tab=contract"
}
}
Pull Request (PR) ์์ฑ : hook๋ฅผ ์ถ๊ฐํ ํ, ์ด ์ ์ฅ์์ ๋ํด pull request๋ฅผ ์์ฑํ์ธ์. PR ์ค๋ช
์ ๋ค์ ์ ๋ณด๋ฅผ ์ถ๊ฐํ์ธ์(๊ฐ์ ๋ณธ์ธ์ ๊ฒ์ผ๋ก ๋ฐ๊พธ์ธ์):
## Register my module
- Module type: `hook`
- Module name: `LicenseCallerWhitelistHook`
- Aeneid Module address: `0x37be56d9fb06d885cda3cb010096c94c28b4d658`
- Mainnet Module address: `0x6d9d51a444c8318e8840e75dab7ed81b5a714610`
- My module is immutable: yes
- My module is using an upgradeable proxy: no
- My module has been verified on the block explorer (required): yes
- Summary of my module: Hook for allowing a licensor to gate which addresses can mint a license. The licensor can add/remove an address at any time.
- GitHub repository with source code and tests: https://github.com/jacob-tucker/license-caller-whitelist-hook
๊ฒ์ฆ ๋๊ธฐ : PR์ด ์ ์ถ๋๋ฉด ๊ฒํ ๋ฉ๋๋ค. ๋ณด์ ๊ฐ์ฌ๊ฐ ์ํ ๋ฐ ์๋ฃ๋๊ณ ๋ชจ๋์ด ํ๋กํ ์ฝ์ ํ์ดํธ๋ฆฌ์คํธ๋ก ๋ฑ๋ก๋๋ฉด, PR์ด ๋ณํฉ๋ฉ๋๋ค. ์ด ์์ ์์ ๋ชจ๋์ ๊ณต์์ ์ผ๋ก ๋ฑ๋ก๋๊ณ DATA Foundation ์ปค๋ฎค๋ํฐ์์ ์ฌ์ฉํ๊ธฐ์ ์์ ํ ๊ฒ์ผ๋ก ์ธ์ ๋ฉ๋๋ค.
์ฌ๋ฌ๋ถ์ ๊ธฐ์ฌ๋ฅผ ๊ธฐ๋ํ๋ฉฐ DATA Foundation ๋ชจ๋ ์ํ๊ณ๋ฅผ ํ์ฅํด ๋๊ฐ๊ธธ ๋ฐ๋๋๋ค!
Commercializer Checker Hooks
๋ฌธ์๊ฐ ๊ณง ์ ๊ณต๋ ์์ ์
๋๋ค. ๊ทธ๋์ ์ง๋ฌธ์ด ์์ผ์๋ฉด Builderโs Discord ์์ ๋ฌธ์ํด ์ฃผ์ธ์.