diff --git a/.gitignore b/.gitignore index f3ea98c..98f36e6 100644 --- a/.gitignore +++ b/.gitignore @@ -12,9 +12,6 @@ deployments broadcast !/broadcast/*/1/ -# Docs -docs/ - # Dotenv file .env diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..146f680 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at . All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6301e30 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,201 @@ +# Contributing + +## Code of Conduct +Please make sure to read and observe our [Code of Conduct](/CODE_OF_CONDUCT.md). + +## Bug Reports + +* Ensure your issue [has not already been reported][1]. It may already be fixed! +* Include the steps you carried out to produce the problem. +* Include the behavior you observed along with the behavior you expected, and + why you expected it. +* Include any relevant traces or debugging output. + +## Feature Requests + +We welcome feedback with or without pull requests. If you have an idea for how +to improve the project, great! All we ask is that you take the time to write a +clear and concise explanation of what need you are trying to solve. If you have +thoughts on _how_ it can be solved, include those too! + +The best way to see a feature added, however, is to submit a pull request. + +## Pull requests + +Pull requests are squash-merged to keep the `main` branch history clean. The title of the pull request becomes the commit message, so it should be written in a consistent format: + +1) Begin with a capital letter. +2) Do not end with a period. +3) Write in the imperative: "Add feature X" and not "Adds feature X" or "Added feature X". + +We welcome conventional commits, with prefixes the title with "fix:" or "feat:". + +Work in progress pull requests should be submitted as Drafts and should **not** be prefixed with "WIP:". + +Branch names don't matter, and commit messages within a pull request mostly don't matter either, although they can help the review process. + +## Find something to work on + +We are always in need of help, be it fixing documentation, reporting bugs or writing some code. +Look at places where you feel best coding practices aren't followed, code refactoring is needed or tests are missing. + +If you have questions about the development process, +feel free to [file an issue](https://github.com/storyprotocol/protocol-periphery-v1/issues/new). + +## Engineering Guidelines + +### Testing + +Code must be thoroughly tested with quality unit tests. + +We defer to the [Foundry Best Practices](https://book.getfoundry.sh/tutorials/best-practices) and [Moloch Testing Guide](https://github.com/MolochVentures/moloch/tree/master/test#readme) for specific recommendations, though not all of it is relevant here. Note the introduction in Moloch Testing Guide: + +> Tests should be written, not only to verify correctness of the target code, but to be comprehensively reviewed by other programmers. Therefore, for mission critical Solidity code, the quality of the tests are just as important (if not more so) than the code itself, and should be written with the highest standards of clarity and elegance. + +Every addition or change to the code must come with relevant and comprehensive tests. + +Flaky tests are not acceptable. + +The test suite should run automatically for every change in the repository, and in pull requests tests must pass before merging. + +The test suite coverage must be kept as close to 100% as possible, enforced in pull requests. + +Test should use Foundry, unless for some reason js or hardhat are needed (for example, upgrades). + +The test function names will follow + +``` +- test_contextCamel_descriptionOfTheTestCamel +- context = method name, contract or functionality. +``` + +In some cases unit tests may be insufficient and complementary techniques should be used: + +1. Property-based tests (aka. fuzzing) for math-heavy code. +2. hardhat test using `hardhat-upgrades` OZ plugin to verify storage and upgradeability (until they support Foundry). +3. Fork tests for upgreadeability to new implementations for upgradeable contracts, testing against the deployed contracts. +4. E2E tests for critical (happy) paths. +5. Formal verification for state machines. + +### Documentation + +For contributors, project guidelines and processes must be documented publicly. + +Every method and contract must have Natspec, using the `///` flavour always. + +For users, features must be abundantly documented. Documentation should include answers to common questions, solutions to common problems, and recommendations for critical decisions that the user may face. + +All changes to the core codebase (excluding tests, auxiliary scripts, etc.) must be documented in a changelog, except for purely cosmetic or documentation changes. + +### Peer review + +All changes must be submitted through pull requests and go through peer code review. + +The review must be approached by the reviewer in a similar way as if it was an audit of the code in question (but importantly it is not a substitute for and should not be considered an audit). + +Reviewers should enforce code and project guidelines. + +External contributions must be reviewed separately by multiple maintainers. + +### Automation + +Automation should be used as much as possible to reduce the possibility of human error and forgetfulness. + +Automations that make use of sensitive credentials must use secure secret management, and must be strengthened against attacks such as [those on GitHub Actions worklows](https://github.com/nikitastupin/pwnhub). + +Some other examples of automation are: + +- Looking for common security vulnerabilities or errors in our code (eg. reentrancy analysis). +- Keeping dependencies up to date and monitoring for vulnerable dependencies. + +### Code style + +Solidity code should be written in a consistent format enforced by a linter, following the official [Solidity Style Guide](https://docs.soliditylang.org/en/latest/style-guide.html). See below for further [Solidity Conventions](#solidity-conventions). + +The code should be simple and straightforward, prioritizing readability and understandability. Consistency and predictability should be maintained across the codebase. In particular, this applies to naming, which should be systematic, clear, and concise. + +Sometimes these guidelines may be broken if doing so brings significant efficiency gains, but explanatory comments should be added. + +Modularity should be pursued, but not at the cost of the above priorities. + +### Solidity Conventions + +In addition to the official Solidity Style Guide we have a number of other conventions that must be followed. + +- Minimize exposing state variables, unless they help with external systems integration or readability. + +- Changes to state should be accompanied by events, and in some cases it is not correct to arbitrarily set state. + +- Internal or private state variables or functions should have an underscore prefix. + + ```solidity + contract TestContract { + uint256 private _privateVar; + uint256 internal _internalVar; + function _testInternal() internal { ... } + function _testPrivate() private { ... } + } + ``` + +* constant or immutable variables must be ALL_CAPS with underscores._ALL_CAPS if private or internal. + +- Events should be emitted immediately after the state change that they + represent, and should be named in the past tense. + + ```solidity + function _burn(address who, uint256 value) internal { + super._burn(who, value); + emit TokensBurned(who, value); + } + ``` + + Some standards (e.g. ERC20) use present tense, and in those cases the + standard specification is used. + +- Interface names should have a capital I prefix. + + ```solidity + interface IERC777 { + ``` + +- Group contracts by functionality within folders if possible. + +- Interfaces should go inside the `interface` folder, mirroring the folder structure of the implementations + +- Folder names must be lowercase, hyphen separated. + + ``` + example-folder + ``` + +- Contract names must be camel case, starting with uppercase letter + + ``` + ExampleContract.sol + ``` + +- Acronyms should be + - Uppercase all if in contract name (`UUPSUpgradeable`, `IPAsset`) + - Camelcase in properties and function names (`ipAssetId`), except if they are defined otherwise in external contracts or interfaces (`tokenURI`) + +- Unchecked arithmetic blocks should contain comments explaining why overflow is guaranteed not to happen. If the reason is immediately apparent from the line above the unchecked block, the comment may be omitted. + +- Interfaces should contain methods an events. Structs showing in an interface should be grouped in a library + +- Function parameter names will have the **suffix** `_` + +- Naming conventions + +- Contract: CamelCase (adjectiveNoun) +- Struct (noun) +- Event (past-tense) +- Function Name (verb noun) + - local variable (noun / compound noun) + - Booleans (use `isXXX`) + - `isValid` + - `valid` + - Modifier (prepositionNoun) + - `onlyOwner` + + +[1]: https://github.com/storyprotocol/protocol-periphery-v1/issues \ No newline at end of file diff --git a/README.md b/README.md index 9265b45..71a6e48 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,143 @@ -## Foundry +# Story Proof-of-Creativity Periphery -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** +[![Version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fstoryprotocol%2Fprotocol-periphery-v1%2Fmain%2Fpackage.json&query=%24.version&label=stable)](https://github.com/storyprotocol/protocol-periphery-v1/releases) +[![Documentation](https://img.shields.io/badge/docs-v1-006B54)](https://docs.story.foundation/docs/what-is-story) +[![Website](https://img.shields.io/badge/website-story-00A170)](https://story.foundation) +[![Discord](https://img.shields.io/badge/discord-join%20chat-5B5EA6)](https://discord.gg/storyprotocol) +[![Twitter Follow](https://img.shields.io/twitter/follow/storyprotocol?style=social)](https://twitter.com/storyprotocol) -Foundry consists of: -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. +Welcome to the Story PoC Periphery repository. This repository contains the peripheral smart contracts for the Story Proof-of-Creativity (PoC) Protocol. These contracts simplify developers’ work by allowing them to bundle multiple interactions with the PoC protocol - like registering an IP Asset and attaching License Terms to that IP Asset - into a single transaction. + +For access to the core PoC contracts, please visit the [protocol-core-v1](https://github.com/storyprotocol/protocol-core-v1) repository. + +> 🚧 WARNING, Beta version: This code is in active development and unaudited. Do not use in production. ## Documentation -https://book.getfoundry.sh/ +>πŸ“˜ **[Learn more about Story](https://docs.storyprotocol.xyz/)** + +Story PoC Periphery combines multiple common independent interactions with the Story PoC Protocol into a single transaction. +For example, this `mintAndRegisterIpAndAttachPILTerms` is one of the functions that allows you to mint an NFT, register it as an IP Asset, and attach License Terms to it all in one call. +```solidity +function mintAndRegisterIpAndAttachPILTerms( + address nftContract, + address recipient, + IPMetadata calldata ipMetadata, + PILTerms calldata terms +) external onlyCallerWithMinterRole(nftContract) returns (address ipId, uint256 tokenId, uint256 licenseTermsId) +``` + +### Supported Workflows +For a list of currently supported workflows, check out the [Workflows documentation](/docs/WORKFLOWS.md). + +### Batching Calls +Batch calling functions is supported both natively and through the `Multicall3` contract. For more information, check out the [Multicall documentation](/docs/MULTICALL.md). -## Usage +### Deployed Contracts -### Build +[![Version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fstoryprotocol%2Fprotocol-periphery-v1%2Fmain%2Fpackage.json&query=%24.version&label=PoC%20Periphery)](https://github.com/storyprotocol/protocol-periphery-v1/releases) contracts are deployed on Story's Iliad Testnet at the following addresses: -```shell -$ forge build +```json +{ + "SPG": "0x69415CE984A79a3Cfbe3F51024C63b6C107331e3", + "SPGNFTBeacon": "0x027D258659FBdda9033f9c008AF166239EBa67c1", + "SPGNFTImpl": "0xDb6480C00B570324A122A6B35F9CAC0F87BDb3e6", + "Multicall3": "0xcA11bde05977b3631167028862bE2a173976CA11" +} ``` -### Test +## Quick Start -```shell -$ forge test +### Prerequisites + +Please install [Foundry / Foundryup](https://github.com/gakonst/foundry) + +### Install dependencies + +```sh +yarn # this installs packages +forge build # this builds ``` -### Format +### Verify upgrade storage layout (before scripts or tests) -```shell -$ forge fmt +```sh +forge clean +forge compile --build-info ``` -### Gas Snapshots +### Helper script to write an upgradeable contract with ERC7201 + +1. Edit `script/foundry/utils/upgrades/ERC7201Helper.s.sol` +2. Change `string constant CONTRACT_NAME = "";` +3. Run the script to generate boilerplate code for storage handling and the namespace hash: -```shell -$ forge snapshot +```sh +forge script script/utils/upgrades/ERC7201Helper.s.sol ``` -### Anvil +4. The log output is the boilerplate code, copy and paste in your contract -```shell -$ anvil +### Testing + +``` +forge test -vvvv ``` -### Deploy +### Coverage -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key ``` +forge coverage +``` + +### Deploying & Upgrading +See [Deploy & Upgrade documentation](./docs/DEPLOY_UPGRADE.md) for more information. + +### Working with a local network -### Cast +Foundry comes with local network [anvil](https://book.getfoundry.sh/anvil/index.html) baked in, and allows us to deploy to our local network for quick testing locally. -```shell -$ cast +To start a local network run: + +``` +make anvil ``` -### Help +This will spin up a local blockchain with a determined private key, so you can use the same private key each time. + +### Code Style + +We employed solhint to check code style. +To check code style with solhint run: -```shell -$ forge --help -$ anvil --help -$ cast --help ``` +make lint +``` + +To re-format code with prettier run: + +``` +make format +``` + +### Security + +We use slither, a popular security framework from [Trail of Bits](https://www.trailofbits.com/). To use slither, you'll first need to [install python](https://www.python.org/downloads/) and [install slither](https://github.com/crytic/slither#how-to-install). + +Then, you can run: + +``` +make slither +``` + +And get your slither output. + + +## Contributing + +Please see our [contribution guidelines](CONTRIBUTING.md). + +## Licensing + +MIT License, details see: [LICENSE](LICENSE). diff --git a/docs/DEPLOY_UPGRADE.md b/docs/DEPLOY_UPGRADE.md new file mode 100644 index 0000000..62c8152 --- /dev/null +++ b/docs/DEPLOY_UPGRADE.md @@ -0,0 +1,66 @@ +# Deploy & Upgrade with Foundry Scripts + + +>πŸ“Œ Note: prior to deployment/upgrade you need to install Foundry, more info [here](https://book.getfoundry.sh/getting-started/installation). + +**πŸ™‹Β Example environment variables**: + +```bash +MAINNET_URL=https://eth-mainnet.g.alchemy.com/v2/1234123412341234 +MAINNET_PRIVATEKEY=0x123456789abcdef +TESTNET_URL=https://testnet.storyrpc.io +TESTNET_PRIVATEKEY=0x123456789abcdef +ETHERSCAN_API_KEY=0x123456789abcdef + +VERIFIER_NAME=blockscout +VERIFIER_URL=https://testnet.storyscan.xyz/api + +SPG_PROXY_ADDR=0x123456789abcdef +SPGNFT_BEACON_ADDR=0x123456789abcdef + +NEW_SPG_IMPL_ADDR= # +NEW_SPGNFT_IMPL_ADDR= # +``` + +## Deployment + +1. Run the [deployment script](script/Main.s.sol) with the following command: + + ```bash + forge script script/Main.s.sol:Main --rpc-url=$TESTNET_URL -vvvv --broadcast --priority-gas-price=1 --legacy --verify --verifier=$VERIFIER_NAME --verifier-url=$VERIFIER_URL + ``` + +2. Set NFT beacon contract for workflow contracts using the admin account by calling `setNFTContractBeacon` with the following command: + + ```bash + cast send $SPG_PROXY_ADDR "setNftContractBeacon(address)" $SPGNFT_BEACON_ADDR --rpc-url=$TESTNET_URL --private-key=$ADMIN_PRIVATEKEY --legacy --gas-limit=1000000 + ``` + + +## Workflow Contract Upgrade + +1. Run the [upgrade script](https://github.com/storyprotocol/protocol-periphery-v1/blob/main/script/UpgradeSPG.s.sol) with the following command: + + ```bash + forge script script/UpgradeSPG.s.sol:UpgradeSPG --rpc-url=$TESTNET_URL -vvvv --broadcast --priority-gas-price=1 --legacy --verify --verifier=$VERIFIER_NAME --verifier-url=$VERIFIER_URL + ``` + +2. Update the proxy contract to point to the newest implementation by calling `upgradeToAndCall` with the following command: + + ```bash + cast send $SPG_PROXY_ADDR "upgradeToAndCall(address,bytes)" $NEW_SPG_IMPL_ADDR "0x" --rpc-url=$TESTNET_URL --private-key=$ADMIN_PRIVATEKEY --legacy --gas-limit=1000000 + ``` + +## SPGNFT Upgrade + +1. Run the [SPGNFT upgrade script](https://github.com/storyprotocol/protocol-periphery-v1/blob/main/script/UpgradeSPGNFT.s.sol) with the following command: + + ```bash + forge script script/UpgradeSPGNFT.s.sol:UpgradeSPGNFT --rpc-url=$TESTNET_URL -vvvv --broadcast --priority-gas-price=1 --legacy --verify --verifier=$VERIFIER_NAME --verifier-url=$VERIFIER_URL + ``` + +2. Update the SPG proxy contract to point to the newest SPGNFT implementation by calling `upgradeCollections` function with the following command: + + ```bash + cast send $SPG_PROXY_ADDR "upgradeCollections(address)" $NEW_SPGNFT_IMPL_ADDR --rpc-url=$TESTNET_URL --private-key=$ADMIN_PRIVATEKEY --legacy --gas-limit=1000000 + ``` diff --git a/MULTICALL.md b/docs/MULTICALL.md similarity index 88% rename from MULTICALL.md rename to docs/MULTICALL.md index 1f5f581..c29abf3 100644 --- a/MULTICALL.md +++ b/docs/MULTICALL.md @@ -1,14 +1,14 @@ -# Batch SPG Function Calls Guide +# Batch Periphery Function Calls ## Background Prior to this point, registering multiple IPs or performing other operations such as minting, attaching licensing terms, and registering derivatives requires separate transactions for each operation. This can be inefficient and costly. To streamline the process, you can batch multiple transactions into a single one. Two solutions are now available for this: -1. **Batch SPG function calls:** Use [SPG's built-in `multicall` function](#batch-spg-function-calls-via-built-in-multicall-function). -2. **Batch function calls beyond SPG:** Use the [Multicall3 Contract](#batch-function-calls-via-multicall3-contract). ---- +1. **Batch workflow function calls:** Use [workflow contract's built-in `multicall` function](#1-batch-workflow-function-calls-via-built-in-multicall-function). +2. **Batch function calls beyond SPG:** Use the [Multicall3 Contract](#2-batch-function-calls-via-multicall3-contract). -## 1. Batch SPG Function Calls via Built-in `multicall` Function -Story Protocol Gateway (SPG) includes a `multicall` function that allows you to combine multiple read or write operations into a single transaction. +## 1. Batch Workflow Function Calls via Built-in `multicall` Function + +Workflow contracts include a `multicall` function that allows you to combine multiple read or write operations into a single transaction. ### Function Definition @@ -23,12 +23,12 @@ function multicall(bytes[] calldata data) external virtual returns (bytes[] memo Suppose you want to mint multiple NFTs, register them as IPs, and link them as derivatives to some parent IPs. -To accomplish this, you can use SPG’s `multicall` function to batch the calls to the `mintAndRegisterIpAndMakeDerivative` function. +To accomplish this, you can use workflow contracts' `multicall` function to batch the calls to the `mintAndRegisterIpAndMakeDerivative` function. Here’s how you might do it: ```solidity -// SPG contract +// StoryProtocolGateway contract contract SPG { ... function mintAndRegisterIpAndMakeDerivative( @@ -73,11 +73,9 @@ await SPG.multicall([ ]); ``` ---- - ## 2. Batch Function Calls via Multicall3 Contract -> ⚠️ **Note:** The Multicall3 contract is not fully compatible with SPG functions that involve SPGNFT minting due to access control and context changes during Multicall execution. For such operations, use [SPG's built-in `multicall` function](#batch-spg-function-calls-via-built-in-multicall-function). +> ⚠️ **Note:** The Multicall3 contract is not fully compatible with workflow functions that involve SPGNFT minting due to access control and context changes during Multicall execution. For such operations, use [workflow contracts' built-in `multicall` function](#1-batch-workflow-function-calls-via-built-in-multicall-function). The Multicall3 contract allows you to execute multiple calls within a single transaction and aggregate the results. The `viem` library provides native support for Multicall3. diff --git a/docs/WORKFLOWS.md b/docs/WORKFLOWS.md new file mode 100644 index 0000000..37a2399 --- /dev/null +++ b/docs/WORKFLOWS.md @@ -0,0 +1,31 @@ +# Supported Workflows + +- `createCollection`: Creates a NFT Collection + +### Final Step: Register an IP Asset + +- `registerIp`: Registers an IP +- `mintAndRegisterIp`: Mints a NFT β†’ Registers it as an IP + +### Final Step: Attach Programmable IP License (PIL) terms to an IP Asset + +- `registerPILTermsAndAttach`: Registers PIL terms β†’ Attaches them to an IP +- `registerIpAndAttachPILTerms`: Registers an IP β†’ Registers PIL terms β†’ Attaches them to the IP +- `mintAndRegisterIpAndAttachPILTerms`: Mints a NFT β†’ Registers it as an IP β†’ Registers PIL terms β†’ Attaches them to the IP. + +### Final Step: Register Derivative IP Asset + +- `registerIpAndMakeDerivative`: Registers an IP β†’ Registers it as a derivative of another IP +- `mintAndRegisterIpAndMakeDerivative`: Mints a NFT β†’ Registers it as an IP β†’ Registers the IP as a derivative of another IP + +- `registerIpAndMakeDerivativeWithLicenseTokens`: Registers an IP β†’ Registers it as a derivative of another IP using the license tokens +- `mintAndRegisterIpAndMakeDerivativeWithLicenseTokens`: Mints a NFT β†’ Registers it as an IP β†’ Registers the IP as a derivative of another IP using the license tokens + +### Final Step: Add IP(s) to a group IP Asset + +- `mintAndRegisterIpAndAttachPILTermsAndAddToGroup`: Mints a NFT β†’ Registers it as an IP β†’ Attaches the given PIL terms to the IP β†’ Adds the IP to a group IP +- `registerIpAndAttachPILTermsAndAddToGroup`: Registers an IP β†’ Attaches the given PIL terms to the IP β†’ Adds the IP to a group IP +- `registerGroupAndAttachPILTermsAndAddIps`: Registers a group IP β†’ Registers PIL terms β†’ Attaches the PIL terms to group IP β†’ Adds existing IPs to the group IP + + +> πŸ“š For full contract interfaces, check out `contracts/interfaces`.