Skip to content

MIP 11 #230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

MIP 11 #230

wants to merge 1 commit into from

Conversation

stranzhay
Copy link
Contributor

No description provided.

Copy link

vercel bot commented May 15, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
mpl-core-js-docs ❌ Failed (Inspect) May 15, 2025 4:18pm

Copy link

coderabbitai bot commented May 15, 2025

Summary by CodeRabbit

  • New Features

    • Introduced comprehensive "group" functionality, enabling creation, management, and hierarchical organization of groups, collections, and assets.
    • Added support for group-level plugins, including adding, updating, approving, and revoking plugins.
    • Implemented group metadata updates and authority management.
    • Enabled closing of groups, with safeguards to ensure groups must be empty before closure.
  • Bug Fixes

    • Added error handling for group-specific scenarios, such as preventing circular references and enforcing authority checks.
  • Tests

    • Added extensive integration tests covering group creation, asset and collection management, plugin operations, metadata updates, and closure scenarios.
  • Documentation

    • Updated program interface documentation to reflect new group instructions, account types, and error codes.
  • Chores

    • Pinned a dependency version for improved build consistency.

End-users can now organize assets and collections into groups, manage group membership and plugins, and utilize enhanced authority and metadata controls.

Walkthrough

This change introduces a comprehensive "group" feature set to the Solana program, including new on-chain account types, instructions, error codes, and supporting logic for hierarchical group management, plugin integration, and metadata updates. It adds extensive Rust integration tests and helper utilities to validate group operations, such as creation, closure, asset/collection membership, plugin management, and authority enforcement. The update also includes new modules for group state, plugin, and utility management, and extends the processor and instruction set to support all group-related workflows.

Changes

File(s) Change Summary
idls/mpl_core.json Added new instructions, account types, argument structs, error codes, and enum variants for group and plugin management to the IDL.
programs/mpl-core/src/state/group.rs
programs/mpl-core/src/state/asset_group_plugin.rs
programs/mpl-core/src/state/collection_group_plugin.rs
Added new state structs for GroupV1, AssetGroupPluginV1, and CollectionGroupPluginV1, including size calculation, authority validation, and serialization logic.
programs/mpl-core/src/state/mod.rs Added new Key enum variants and publicly re-exported new group and plugin modules.
programs/mpl-core/src/processor/group/mod.rs
programs/mpl-core/src/processor/group/assets.rs
programs/mpl-core/src/processor/group/child_groups.rs
programs/mpl-core/src/processor/group/close.rs
programs/mpl-core/src/processor/group/collections.rs
programs/mpl-core/src/processor/group/create.rs
programs/mpl-core/src/processor/group/metadata.rs
Introduced modules and functions for group creation, closure, metadata updates, asset/collection/child group management, and authority validation.
programs/mpl-core/src/processor/mod.rs Registered new group instructions in the processor and routed them to corresponding handlers.
programs/mpl-core/src/instruction.rs Added new instruction variants for group and plugin management, with account metadata and argument imports.
programs/mpl-core/src/plugins/group_plugins.rs
programs/mpl-core/src/plugins/mod.rs
Implemented group-level plugin management functions and exposed the new plugin module.
programs/mpl-core/src/utils/group.rs
programs/mpl-core/src/utils/mod.rs
Added utility functions for group plugin PDA derivation and cycle detection; registered the new utils module.
programs/mpl-core/src/error.rs Added new error variants for group and collection operations.
programs/mpl-core/Cargo.toml
Cargo.toml
Pinned ahash dependency in one Cargo.toml and added a blank line in another.
clients/rust/tests/child_groups.rs
clients/rust/tests/close_group.rs
clients/rust/tests/create_collection_asset.rs
clients/rust/tests/create_group_with_links.rs
clients/rust/tests/group_assets.rs
clients/rust/tests/group_collections.rs
clients/rust/tests/group_plugins.rs
clients/rust/tests/update_group_metadata.rs
Added comprehensive async integration tests for group creation, membership management, plugin handling, authority enforcement, and metadata updates.
clients/rust/tests/setup/group.rs
clients/rust/tests/setup/mod.rs
Added and exposed a helper function for creating test groups in integration tests.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Program
    participant GroupAccount
    participant CollectionAccount
    participant AssetAccount
    participant PluginAccount

    %% Group Creation with Initial Links
    Client->>Program: CreateGroup (with initial collections/parents)
    Program->>GroupAccount: Initialize GroupV1
    alt With collections
        Program->>CollectionAccount: Validate & Link
        Program->>PluginAccount: Upsert CollectionGroupPluginV1
    end
    alt With parent groups
        Program->>GroupAccount: Validate Parent
        Program->>GroupAccount: Link Parent/Child
    end
    Program-->>Client: Success

    %% Add Asset to Group
    Client->>Program: AddAssetsToGroup (group, assets, authorities)
    Program->>GroupAccount: Validate authority & update asset list
    Program->>AssetAccount: Validate authority
    Program->>PluginAccount: Upsert AssetGroupPluginV1
    Program-->>Client: Success

    %% Add Plugin to Group
    Client->>Program: AddGroupPlugin (group, plugin, authority)
    Program->>GroupAccount: Validate authority
    Program->>GroupAccount: Add plugin to allowed_plugins
    Program-->>Client: Success

    %% Close Group
    Client->>Program: CloseGroup (group, authority)
    Program->>GroupAccount: Validate authority & group is empty
    Program->>GroupAccount: Close account, return lamports
    Program-->>Client: Success or Error (if not empty)
Loading

Suggested reviewers

  • nhanphan
  • MarkSackerberg

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@stranzhay
Copy link
Contributor Author

we still need an alt name besides 'group', can do a find and replace once decided

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 51

🔭 Outside diff range comments (1)
idls/mpl_core.json (1)

2801-2865: ⚠️ Potential issue

Critical: GroupV1 struct missing capacity fields
You accept maxCollections, maxAssets, maxGroups, and maxPlugins in CreateGroupArgs but do not store them in the GroupV1 account. Without persisting these limits, enforcement will be impossible.

Add the following fields to GroupV1:

   {
     "name": "GroupV1",
     "type": {
       "kind": "struct",
       "fields": [
         { "name": "key", "type": { "defined": "Key" } },
         { "name": "updateAuthority", "type": "publicKey" },
         { "name": "delegatedAuthority", "type": { "option": "publicKey" } },
         { "name": "name", "type": "string" },
         { "name": "uri", "type": "string" },
+        { "name": "maxCollections", "type": "u32" },
+        { "name": "maxAssets",      "type": "u32" },
+        { "name": "maxGroups",      "type": "u32" },
+        { "name": "maxPlugins",     "type": "u32" },
         { "name": "collections", "type": { "vec": "publicKey" } },
         { "name": "assets",      "type": { "vec": "publicKey" } },
         { "name": "childGroups", "type": { "vec": "publicKey" } },
♻️ Duplicate comments (1)
clients/rust/tests/child_groups.rs (1)

172-179: Same index brittleness in removal path

See previous comment – consider refactor for maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1460e5 and 82c873c.

⛔ Files ignored due to path filters (49)
  • clients/js/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • clients/js/src/generated/accounts/assetGroupPluginV1.ts is excluded by !**/generated/**
  • clients/js/src/generated/accounts/collectionGroupPluginV1.ts is excluded by !**/generated/**
  • clients/js/src/generated/accounts/groupV1.ts is excluded by !**/generated/**
  • clients/js/src/generated/accounts/index.ts is excluded by !**/generated/**
  • clients/js/src/generated/errors/mplCore.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/addAssetsToGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/addCollectionsToGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/addGroupPlugin.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/addGroupsToGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/approveGroupPlugin.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/closeGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/createGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/index.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/removeAssetsFromGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/removeCollectionsFromGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/removeGroupPlugin.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/removeGroupsFromGroup.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/revokeGroupPlugin.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/updateGroupMetadata.ts is excluded by !**/generated/**
  • clients/js/src/generated/instructions/updateGroupPlugin.ts is excluded by !**/generated/**
  • clients/js/src/generated/types/allowedPlugin.ts is excluded by !**/generated/**
  • clients/js/src/generated/types/index.ts is excluded by !**/generated/**
  • clients/js/src/generated/types/key.ts is excluded by !**/generated/**
  • clients/js/src/generated/types/pluginAuthorityType.ts is excluded by !**/generated/**
  • clients/rust/src/generated/accounts/asset_group_plugin_v1.rs is excluded by !**/generated/**
  • clients/rust/src/generated/accounts/collection_group_plugin_v1.rs is excluded by !**/generated/**
  • clients/rust/src/generated/accounts/group_v1.rs is excluded by !**/generated/**
  • clients/rust/src/generated/accounts/mod.rs is excluded by !**/generated/**
  • clients/rust/src/generated/errors/mpl_core.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/add_assets_to_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/add_collections_to_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/add_group_plugin.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/add_groups_to_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/approve_group_plugin.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/close_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/create_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/mod.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/remove_assets_from_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/remove_collections_from_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/remove_group_plugin.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/remove_groups_from_group.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/revoke_group_plugin.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/update_group_metadata.rs is excluded by !**/generated/**
  • clients/rust/src/generated/instructions/update_group_plugin.rs is excluded by !**/generated/**
  • clients/rust/src/generated/types/allowed_plugin.rs is excluded by !**/generated/**
  • clients/rust/src/generated/types/key.rs is excluded by !**/generated/**
  • clients/rust/src/generated/types/mod.rs is excluded by !**/generated/**
  • clients/rust/src/generated/types/plugin_authority_type.rs is excluded by !**/generated/**
📒 Files selected for processing (31)
  • Cargo.toml (1 hunks)
  • clients/rust/tests/child_groups.rs (1 hunks)
  • clients/rust/tests/close_group.rs (1 hunks)
  • clients/rust/tests/create_collection_asset.rs (1 hunks)
  • clients/rust/tests/create_group_with_links.rs (1 hunks)
  • clients/rust/tests/group_assets.rs (1 hunks)
  • clients/rust/tests/group_collections.rs (1 hunks)
  • clients/rust/tests/group_plugins.rs (1 hunks)
  • clients/rust/tests/setup/group.rs (1 hunks)
  • clients/rust/tests/setup/mod.rs (1 hunks)
  • clients/rust/tests/update_group_metadata.rs (1 hunks)
  • idls/mpl_core.json (8 hunks)
  • programs/mpl-core/Cargo.toml (1 hunks)
  • programs/mpl-core/src/error.rs (1 hunks)
  • programs/mpl-core/src/instruction.rs (2 hunks)
  • programs/mpl-core/src/plugins/group_plugins.rs (1 hunks)
  • programs/mpl-core/src/plugins/mod.rs (2 hunks)
  • programs/mpl-core/src/processor/group/assets.rs (1 hunks)
  • programs/mpl-core/src/processor/group/child_groups.rs (1 hunks)
  • programs/mpl-core/src/processor/group/close.rs (1 hunks)
  • programs/mpl-core/src/processor/group/collections.rs (1 hunks)
  • programs/mpl-core/src/processor/group/create.rs (1 hunks)
  • programs/mpl-core/src/processor/group/metadata.rs (1 hunks)
  • programs/mpl-core/src/processor/group/mod.rs (1 hunks)
  • programs/mpl-core/src/processor/mod.rs (3 hunks)
  • programs/mpl-core/src/state/asset_group_plugin.rs (1 hunks)
  • programs/mpl-core/src/state/collection_group_plugin.rs (1 hunks)
  • programs/mpl-core/src/state/group.rs (1 hunks)
  • programs/mpl-core/src/state/mod.rs (2 hunks)
  • programs/mpl-core/src/utils/group.rs (1 hunks)
  • programs/mpl-core/src/utils/mod.rs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
clients/rust/tests/setup/mod.rs (1)
clients/rust/tests/setup/group.rs (1)
  • create_test_group (21-60)
programs/mpl-core/src/state/mod.rs (11)
clients/js/src/generated/accounts/groupV1.ts (1)
  • GroupV1 (41-41)
clients/js/src/generated/accounts/collectionGroupPluginV1.ts (1)
  • CollectionGroupPluginV1 (30-31)
clients/js/src/generated/accounts/assetGroupPluginV1.ts (1)
  • AssetGroupPluginV1 (30-30)
clients/rust/src/generated/instructions/add_collections_to_group.rs (2)
  • group (105-108)
  • group (300-303)
clients/rust/src/generated/instructions/add_assets_to_group.rs (2)
  • group (103-106)
  • group (296-299)
clients/rust/src/generated/instructions/add_group_plugin.rs (2)
  • group (130-133)
  • group (387-390)
clients/rust/src/generated/instructions/approve_group_plugin.rs (2)
  • group (111-114)
  • group (312-315)
clients/rust/src/generated/instructions/close_group.rs (2)
  • group (89-92)
  • group (254-257)
clients/rust/src/generated/instructions/create_group.rs (2)
  • group (133-136)
  • group (422-425)
clients/rust/src/generated/instructions/remove_assets_from_group.rs (2)
  • group (105-108)
  • group (300-303)
clients/rust/src/generated/instructions/remove_collections_from_group.rs (2)
  • group (105-108)
  • group (300-303)
clients/rust/tests/setup/group.rs (1)
clients/rust/src/generated/instructions/create_group.rs (14)
  • system_program (149-152)
  • system_program (437-443)
  • group (133-136)
  • group (422-425)
  • update_authority (139-145)
  • update_authority (428-434)
  • max_collections (164-167)
  • max_collections (455-458)
  • max_assets (169-172)
  • max_assets (460-463)
  • max_groups (174-177)
  • max_groups (465-468)
  • max_plugins (179-182)
  • max_plugins (470-473)
programs/mpl-core/src/state/collection_group_plugin.rs (3)
programs/mpl-core/src/state/asset_group_plugin.rs (3)
  • size (35-37)
  • len (41-43)
  • key (47-49)
programs/mpl-core/src/state/group.rs (5)
  • size (129-150)
  • len (34-36)
  • len (55-57)
  • len (160-169)
  • key (154-156)
programs/mpl-core/src/state/mod.rs (2)
  • len (67-74)
  • len (116-118)
clients/rust/tests/create_collection_asset.rs (5)
clients/js/src/generated/types/freezeDelegate.ts (1)
  • FreezeDelegate (11-11)
clients/js/src/generated/types/plugin.ts (1)
  • Plugin (68-84)
clients/js/src/generated/types/pluginAuthorityPair.ts (1)
  • PluginAuthorityPair (24-27)
clients/rust/tests/setup/mod.rs (6)
  • program_test (15-17)
  • create_collection (195-224)
  • create_asset (40-73)
  • assert_asset (86-181)
  • assert_collection (238-341)
  • airdrop (343-361)
clients/js/test/_setupRaw.ts (2)
  • CreateCollectionHelperArgs (82-89)
  • CreateAssetHelperArgs (32-43)
programs/mpl-core/src/state/asset_group_plugin.rs (4)
programs/mpl-core/src/state/collection_group_plugin.rs (3)
  • size (35-37)
  • len (41-43)
  • key (47-49)
programs/mpl-core/src/state/group.rs (5)
  • size (129-150)
  • len (34-36)
  • len (55-57)
  • len (160-169)
  • key (154-156)
programs/mpl-core/src/plugins/mod.rs (2)
  • len (118-144)
  • len (212-214)
programs/mpl-core/src/state/mod.rs (2)
  • len (67-74)
  • len (116-118)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Rust Client / Test
🔇 Additional comments (56)
Cargo.toml (1)

11-11: Looks good - simple formatting change.

This is a minor whitespace formatting change with no functional impact.

programs/mpl-core/src/utils/mod.rs (1)

1-4: Looks good - clean module organization.

The new group utility module and explanatory comment follow a clear organization pattern, maintaining consistency with the existing codebase structure and documentation style.

clients/rust/tests/setup/mod.rs (1)

392-393: Good test structure for new group functionality.

The addition of the group module and re-export of the create_test_group function provides a clean interface for setting up test groups in the extensive new test suite. This supports proper testing of the new hierarchical group management features.

Based on the relevant code snippets, the create_test_group function implements sensible defaults for customizable group properties, making it flexible for various test scenarios.

programs/mpl-core/src/plugins/mod.rs (1)

3-3: Module structure looks good!

The addition of the group_plugins module and its public re-export aligns with the broader group functionality being introduced. This follows the established pattern in the codebase of separating concerns into distinct modules and maintaining a clean public API.

Also applies to: 12-12

programs/mpl-core/src/error.rs (1)

216-238: Error handling for group operations looks comprehensive.

The new error variants properly cover the different failure modes for group operations:

  • Missing groups or collections
  • Circular references in group hierarchies
  • Groups with remaining linked entities
  • Invalid operations
  • Plugin restrictions

The error codes follow the sequential numbering pattern and have clear, descriptive messages.

programs/mpl-core/src/state/mod.rs (1)

103-108: Account type discriminators added correctly.

The new Key enum variants provide proper discriminators for the group-related account types, maintaining the established pattern for account identification within the program.

programs/mpl-core/src/processor/group/close.rs (2)

22-30: Thorough emptiness check before closure.

The implementation properly verifies all collections that could make a group non-empty:

  • Collections
  • Child groups
  • Parent groups
  • Assets
  • Allowed plugins

This prevents accidental loss of references when closing groups that still have linked entities.


7-34:

❓ Verification inconclusive

Solid implementation of the group closure logic.

The function follows best practices for account validation and authority checking:

  • Properly extracts and validates required accounts
  • Ensures the authority is a signer
  • Checks that the group is empty before allowing closure
  • Returns appropriate errors for each failure case

Ensure the group account's program owner is validated before closing it:


🏁 Script executed:

#!/bin/bash
# Check if program owner validation is implemented elsewhere

# Look for owner checks in imported utility functions
cat programs/mpl-core/src/utils/mod.rs | grep -A 10 "close_program_account"

Length of output: 75


🏁 Script executed:

#!/bin/bash
# Locate the definition of close_program_account and inspect its implementation
rg -n "fn close_program_account" -n programs/mpl-core/src
# Also search all usages to ensure owner validation isn’t happening elsewhere
rg -n "close_program_account" -n programs/mpl-core/src

Length of output: 713


🏁 Script executed:

#!/bin/bash
# Inspect the implementation of close_program_account for owner checks
rg -n "fn close_program_account" -C 5 programs/mpl-core/src/utils/account.rs

Length of output: 380


🏁 Script executed:

#!/bin/bash
# Retrieve the full implementation of close_program_account to check for owner validation
rg -n "pub(crate) fn close_program_account" -A 100 programs/mpl-core/src/utils/account.rs

Length of output: 91


🏁 Script executed:

#!/bin/bash
# Retrieve the full implementation of close_program_account for owner validation analysis
rg -n "fn close_program_account" -A 200 programs/mpl-core/src/utils/account.rs

Length of output: 2693


🏁 Script executed:

#!/bin/bash
# Inspect GroupV1::load implementation for owner validation
rg -n "impl GroupV1" -A 200 programs/mpl-core/src

Length of output: 6280


Ensure the group account is owned by this program before closing

Before invoking close_program_account, there’s no explicit check that group_info.owner == &crate::ID, which could allow closing accounts not owned by this program. Please add (or confirm via GroupV1::load) an owner check:

• File: programs/mpl-core/src/processor/group/close.rs
Insert before line 33 (before close_program_account):

if group_info.owner != &crate::ID {
    return Err(MplCoreError::InvalidOwner.into());
}

or, if you have an assert_owned_by helper:

assert_owned_by(group_info, &crate::ID)?;

This guarantees only accounts owned by the MPL Core program can be closed.

programs/mpl-core/src/processor/group/metadata.rs (1)

36-43: Authority check looks solid

The signer assertion followed by validate_authority provides a clear 2-step verification and prevents privilege escalation.

clients/rust/tests/setup/group.rs (1)

30-44: Nice helper – but update_authority may need to sign

When the caller passes Some(pubkey) that ≠ context.payer, the transaction will lack the corresponding signature, causing tests to fail unexpectedly.
Either (a) document that the provided authority must be context.payer, or (b) add it to the signers list when it differs.

clients/rust/tests/child_groups.rs (2)

250-285: Great negative test for circular reference

Covers an important edge case; assert looks good.


334-341: Back-pointer check is valuable

Ensures bidirectional integrity after removal – nice.

programs/mpl-core/src/processor/mod.rs (3)

11-11: Good addition of the group module.

The module declaration follows the existing pattern in the codebase and properly integrates with the rest of the modules.


32-32: Module export looks good.

The public re-export of the group module maintains consistency with other module exports.


187-243: Well-structured instruction handlers for group operations.

The additions to the instruction processor correctly handle the new group-related instructions following the same pattern as existing code. Each instruction is properly logged and delegated to its specific handler function. The comprehensive set of operations provides a complete API for group management, including creation, closure, metadata management, and various membership operations.

clients/rust/tests/update_group_metadata.rs (3)

16-36: Good helper function for metadata verification.

The assert_group_metadata helper function is well-designed, keeping the test code DRY by providing a reusable way to verify group metadata fields.


38-80: Thorough success test case.

This test covers the happy path for updating group metadata with good test setup, execution, and verification steps. It tests all updatable fields (name, URI, and update authority).


82-130: Good error handling test.

The test properly verifies that:

  1. Using an invalid authority results in the expected error
  2. The metadata remains unchanged after a failed update attempt

This negative testing is crucial for security and data integrity.

programs/mpl-core/src/state/collection_group_plugin.rs (3)

7-17: Well-structured account data type.

The CollectionGroupPluginV1 struct is properly designed with:

  • Clear documentation
  • Appropriate account discriminator
  • Necessary fields for tracking collection-to-group relationships
  • Size annotations for serialization

19-38: Good implementation of constructor and size calculation.

The implementation:

  • Correctly defines the constant base length
  • Provides a clean constructor method
  • Accurately calculates allocation size based on max groups

The size calculation properly accounts for both fixed-size components and the variable-length vector of group pubkeys.


40-50: Appropriate trait implementations.

The implementations of DataBlob and SolanaAccount traits are correct:

  • len() accurately returns the current size based on groups count
  • key() returns the appropriate discriminator

These implementations enable proper serialization and account validation.

programs/mpl-core/src/state/asset_group_plugin.rs (3)

7-17: Well-structured asset group plugin account.

Similar to the collection group plugin, this account type is properly designed with clear documentation, appropriate fields, and serialization support. The struct handles tracking an asset's membership across multiple groups.


19-38: Good implementation of constructor and size utilities.

The implementation correctly:

  • Defines the base length constant
  • Provides a constructor for new instances
  • Calculates account size requirements based on maximum group count

40-50: Solid trait implementations.

The trait implementations for DataBlob and SolanaAccount are correct, providing:

  • Accurate current length calculation
  • Proper key identification

This ensures the account can be correctly serialized, deserialized, and identified.

programs/mpl-core/src/instruction.rs (1)

364-370: Confirm plugin_program should really be a required account

plugin_program (idx 3) is currently annotated as a mandatory, read-only account.
In most plugin workflows the CPI target program ID can normally be inferred from the plugin account’s data and therefore does not have to be passed explicitly – or it can be passed optionally if some plugins do not require it.

For on-chain size and CI-fee reasons you may want to declare this account as optional (and even remove it when not needed) to keep the account list minimal.

If you intentionally enforce an explicit program ID, please document the rationale in the doc-comment above the variant so downstream SDK builders understand why an extra account is required.

clients/rust/tests/create_group_with_links.rs (1)

120-125: Order of remaining accounts must match on-chain validation

The instruction appends [collection, collection_update_auth, parent_group, parent_update_auth].
If the on-chain processor expects the update-authority directly after each resource account, the ordering is correct.

Double-check the processor logic; a mismatch will throw “account out of order” errors which are painful to debug in integration tests.

clients/rust/tests/close_group.rs (1)

84-87: Make the refund check deterministic.

payer_after > payer_before passes even if only 1-lamport was refunded.
Capturing the group’s lamports before closing lets you assert the exact delta and removes non-determinism introduced by rent changes.

-assert!(payer_after > payer_before, "Payer should receive lamports from the closed account");
+let refunded = payer_after - payer_before;
+assert_eq!(
+    refunded,
+    group_account_before.lamports, // record this just before issuing the close ix
+    "Payer should receive the full balance of the closed account"
+);

[ suggest_nitpick ]

programs/mpl-core/src/processor/group/child_groups.rs (1)

121-134: Vector shrink uses swap_remove – order-agnostic but O(1)

Nice touch using swap_remove; order of child_groups / parent_groups isn’t semantically important and you save an O(n) shift. 👍

programs/mpl-core/src/state/group.rs (2)

137-150: size helper omits Option worst-case

BASE_LEN reserves 1 + 32 bytes for delegated_authority, but size() doesn’t account for the variable nature of Option.
Callers wanting “worst-case” space (e.g. alloc account upfront) might under-allocate if they later set a delegate.

Either document that size() assumes a None delegate or add + 32 to cover the Some case when max_delegate = true.


117-126: 🧹 Nitpick (assertive)

validate_authority ignores delegated_authority == update_authority edge-case

If someone mistakenly sets delegated_authority equal to update_authority, the delegated key is effectively duplicated.
Unifying the check prevents silent config errors:

-if &self.update_authority != authority {
+if authority != &self.update_authority {
     match self.delegated_authority {
-        Some(pubkey) if &pubkey == authority => Ok(()),
+        Some(pubkey) if &pubkey == authority && pubkey != self.update_authority => Ok(()),

Likely an incorrect or invalid review comment.

programs/mpl-core/src/plugins/group_plugins.rs (1)

158-161: update_group_plugin currently performs no state change

After authority checks it returns Ok(()). If this is intentional (e.g. the plugin program handles updates), document that; otherwise this is incomplete functionality.

idls/mpl_core.json (25)

2117-2166: New CreateGroup instruction looks correct
Accounts and arguments align with the intended flow for creating a group account (payer, PDA, update authority, system program). The discriminant value (33) follows the previous instruction. Args reference CreateGroupArgs which is defined later.


2167-2192: CloseGroup instruction is properly defined
Using the updateAuthority as the lamports recipient and closing the group PDA is consistent. Discriminant value (34) is sequential.


2193-2225: UpdateGroupMetadata covers name/URI/authority updates
Mapping to UpdateGroupMetadataArgs is correct, and the authority guard is in place. Discriminant (35) is sequential.


2226-2258: AddCollectionsToGroup instruction is well-defined
The authority signer and mutable group account match expectations. Args type AddCollectionsToGroupArgs is available. Discriminant (36) is correct.


2259-2291: RemoveCollectionsFromGroup instruction is well-defined
Mirrors the AddCollections instruction with matching args type and correct discriminant (37).


2292-2324: AddAssetsToGroup instruction is well-defined
Uses AddAssetsToGroupArgs correctly and follows the sequential discriminant (38).


2325-2357: RemoveAssetsFromGroup instruction is well-defined
Args, accounts, and discriminant (39) are consistent with the AddAssets instruction.


2424-2480: AddGroupPlugin instruction integrates plugin support
Accounts include pluginProgram for on-chain validation, and the args AddGroupPluginArgs is defined. Discriminant (42) flows correctly.


2481-2514: RemoveGroupPlugin instruction is correct
No args needed, and discriminant (43) is sequential.


2515-2555: UpdateGroupPlugin instruction defined properly
Maps to UpdateGroupPluginArgs and uses the correct authority guard. Discriminant (44) is valid.


2556-2596: ApproveGroupPlugin instruction looks good
Accounts, args (ApproveGroupPluginArgs), and discriminant (45) follow the pattern of plugin management.


2597-2630: RevokeGroupPlugin instruction is correct
Follows RemoveGroupPlugin in structure with discriminant (46).


2719-2742: AssetGroupPluginV1 account type is appropriate
Defines the linkage between an asset and its associated groups. Fields (asset and groups) are coherent.


2743-2776: CollectionV1 struct extended with metadata fields
Adding name, uri, numMinted, and currentSize supports on-chain group operations and display logic.


2777-2800: CollectionGroupPluginV1 account type is appropriate
Mirrors the asset plugin structure for collections.


3490-3522: Plugin argument types are in place
AddGroupPluginArgs, UpdateGroupPluginArgs, and ApproveGroupPluginArgs align with the new plugin workflow.


4201-4231: Group asset/authority indices types are correct
AddAssetsToGroupArgs and RemoveAssetsFromGroupArgs use byte arrays for indices; this is consistent with similar IDL patterns.


4233-4263: Group group/authority indices types are correct
AddGroupsToGroupArgs and RemoveGroupsFromGroupArgs follow the same pattern.


4265-4295: Group collection/authority indices types are correct
AddCollectionsToGroupArgs and RemoveCollectionsFromGroupArgs are consistent with other membership instructions.


4297-4345: CreateGroupArgs struct covers initial state
Fields match CreateGroup requirements. Remember to update GroupV1 to store max values (see above).


4347-4371: UpdateGroupMetadataArgs struct is correct
Supports optional update of name, URI, and delegated authority.


4712-4729: AllowedPlugin struct supports plugin lists
The address and authorityType fields align with PluginAuthorityType.


5621-5632: Key enum extended with Group types
Variants GroupV1, CollectionGroupPluginV1, and AssetGroupPluginV1 are correctly appended.


5635-5653: PluginAuthorityType enum is defined appropriately
Variants None, UpdateAuthority, and SpecificAddress cover all authority models.


5935-5963: New group-specific error codes are added
Codes 51–56 cover all necessary group error conditions consecutively.

Comment on lines +27 to +28
[patch.crates-io]
ahash = "=0.8.7"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Good practice pinning the ahash dependency.

Pinning the ahash version to exactly 0.8.7 ensures consistent hashing behavior across all dependencies in the crate graph, which is crucial for stability when handling complex data structures in the new group functionality.

Consider adding a comment explaining why this specific version was chosen, for future maintainers:

 [patch.crates-io]
-ahash = "=0.8.7"
+ahash = "=0.8.7" # Pinned to ensure consistent hashing behavior for group data structures
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[patch.crates-io]
ahash = "=0.8.7"
[patch.crates-io]
ahash = "=0.8.7" # Pinned to ensure consistent hashing behavior for group data structures
🤖 Prompt for AI Agents
In programs/mpl-core/Cargo.toml around lines 27 to 28, add a comment above the
ahash dependency pinning that explains why version 0.8.7 is specifically chosen.
This comment should mention that pinning this exact version ensures consistent
hashing behavior across dependencies, which is important for stability in
handling complex data structures in the new group functionality.

Comment on lines +157 to +164
mod group;
pub use group::*;

mod collection_group_plugin;
pub use collection_group_plugin::*;

mod asset_group_plugin;
pub use asset_group_plugin::*;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider reorganizing module declarations.

While the module additions themselves look good, they're placed after the test module rather than grouped with the other module declarations at the top of the file. Consider moving these module declarations to be with the other modules for better code organization and readability.

-mod tests {
-    use strum::IntoEnumIterator;
-
-    use super::*;
-
-    #[test]
-    fn test_authority_len() {
-        let authorities = vec![
-            Authority::None,
-            Authority::Owner,
-            Authority::UpdateAuthority,
-            Authority::Address {
-                address: Pubkey::default(),
-            },
-        ];
-        assert_eq!(
-            authorities.len(),
-            Authority::COUNT,
-            "Must test all Authority variants"
-        );
-        for authority in authorities {
-            let serialized = authority.try_to_vec().unwrap();
-
-            assert_eq!(serialized.len(), authority.len());
-        }
-    }
-
-    #[test]
-    fn test_key_len() {
-        for key in Key::iter() {
-            let serialized = key.try_to_vec().unwrap();
-            assert_eq!(serialized.len(), key.len());
-        }
-    }
-}
-
-mod group;
-pub use group::*;
-
-mod collection_group_plugin;
-pub use collection_group_plugin::*;
-
-mod asset_group_plugin;
-pub use asset_group_plugin::*;
+mod group;
+pub use group::*;
+
+mod collection_group_plugin;
+pub use collection_group_plugin::*;
+
+mod asset_group_plugin;
+pub use asset_group_plugin::*;
+
+mod tests {
+    use strum::IntoEnumIterator;
+
+    use super::*;
+
+    #[test]
+    fn test_authority_len() {
+        let authorities = vec![
+            Authority::None,
+            Authority::Owner,
+            Authority::UpdateAuthority,
+            Authority::Address {
+                address: Pubkey::default(),
+            },
+        ];
+        assert_eq!(
+            authorities.len(),
+            Authority::COUNT,
+            "Must test all Authority variants"
+        );
+        for authority in authorities {
+            let serialized = authority.try_to_vec().unwrap();
+
+            assert_eq!(serialized.len(), authority.len());
+        }
+    }
+
+    #[test]
+    fn test_key_len() {
+        for key in Key::iter() {
+            let serialized = key.try_to_vec().unwrap();
+            assert_eq!(serialized.len(), key.len());
+        }
+    }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mod group;
pub use group::*;
mod collection_group_plugin;
pub use collection_group_plugin::*;
mod asset_group_plugin;
pub use asset_group_plugin::*;
mod group;
pub use group::*;
mod collection_group_plugin;
pub use collection_group_plugin::*;
mod asset_group_plugin;
pub use asset_group_plugin::*;
mod tests {
use strum::IntoEnumIterator;
use super::*;
#[test]
fn test_authority_len() {
let authorities = vec![
Authority::None,
Authority::Owner,
Authority::UpdateAuthority,
Authority::Address {
address: Pubkey::default(),
},
];
assert_eq!(
authorities.len(),
Authority::COUNT,
"Must test all Authority variants"
);
for authority in authorities {
let serialized = authority.try_to_vec().unwrap();
assert_eq!(serialized.len(), authority.len());
}
}
#[test]
fn test_key_len() {
for key in Key::iter() {
let serialized = key.try_to_vec().unwrap();
assert_eq!(serialized.len(), key.len());
}
}
}
🤖 Prompt for AI Agents
In programs/mpl-core/src/state/mod.rs around lines 157 to 164, the new module
declarations are placed after the test module, which disrupts the logical
grouping of module imports. Move the declarations of group,
collection_group_plugin, and asset_group_plugin modules to be alongside the
other module declarations at the top of the file to improve code organization
and readability.

Comment on lines +45 to +50
if let Some(name) = args.name {
group.name = name;
}
if let Some(uri) = args.uri {
group.uri = uri;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Bounds check for name / uri length missing

A malicious client could supply a huge string, blowing the account’s size and DoS-ing deserialize.
Consider enforcing a reasonable max length (e.g. 256 chars) consistent with creation logic.

🤖 Prompt for AI Agents
In programs/mpl-core/src/processor/group/metadata.rs around lines 45 to 50, the
code assigns `name` and `uri` from `args` to `group` without checking their
length, which risks DoS from overly large strings. Add a length check before
assignment to ensure `name` and `uri` do not exceed a maximum length (e.g., 256
characters). Only assign the values if they pass this length validation to
prevent oversized data from causing issues.

Comment on lines +45 to +53
if let Some(name) = args.name {
group.name = name;
}
if let Some(uri) = args.uri {
group.uri = uri;
}
if let Some(new_auth) = args.new_update_authority {
group.update_authority = new_auth;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Updating update_authority without verifying the new signer

new_update_authority can be set to an arbitrary pubkey that is not a signer of the current tx.
That means the current authority could mistakenly type a wrong key and irreversibly lock the group.
Consider requiring the new authority to be supplied in accounts[2] and asserted with assert_signer, or emit a warning/event when new_auth is not a signer.

+// 2 optional –– new authority must sign if being set
+if let Some(new_auth) = args.new_update_authority {
+    let new_auth_info = accounts.get(2).ok_or(MplCoreError::MissingUpdateAuthority)?;
+    assert_eq!(new_auth, *new_auth_info.key);
+    assert_signer(new_auth_info)?;
+    group.update_authority = new_auth;
+}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In programs/mpl-core/src/processor/group/metadata.rs around lines 45 to 53, the
code updates the group's update_authority without verifying that the new
authority is a signer of the transaction, which risks locking the group if an
incorrect key is provided. To fix this, require the new_update_authority to be
passed as a separate account (e.g., accounts[2]) and use assert_signer to verify
it is a signer before assigning it to group.update_authority. Alternatively,
emit a warning or event if the new authority is not a signer to alert about the
potential issue.

Comment on lines +55 to +61
// Save
let serialized = group.try_to_vec()?;
sol_memcpy(
&mut group_info.try_borrow_mut_data()?[0..serialized.len()],
&serialized,
serialized.len(),
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Partial memcpy may leave stale bytes → future deserialize failures

try_to_vec()’s length can shrink (e.g., shorter name).
sol_memcpy only overwrites the first serialized.len() bytes, leaving trailing bytes from the previous state untouched; Borsh will later error because extra bytes remain.
Zero-fill the whole buffer or assert equal size.

 let mut data = group_info.try_borrow_mut_data()?;
-let dst = &mut data[0..serialized.len()];
-sol_memcpy(dst, &serialized, serialized.len());
+// wipe then copy to avoid stale tail bytes
+data.fill(0);
+sol_memcpy(&mut data[..serialized.len()], &serialized, serialized.len());

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In programs/mpl-core/src/processor/group/metadata.rs around lines 55 to 61, the
current code copies only the serialized data length into the buffer, potentially
leaving stale bytes from previous data which can cause deserialization errors.
To fix this, either zero-fill the entire buffer before copying or assert that
the serialized data length matches the buffer length exactly, ensuring no
leftover bytes remain after the memcpy operation.

Comment on lines +108 to +113
sol_memcpy(
&mut group_info.try_borrow_mut_data()?[..serialized_group.len()],
&serialized_group,
serialized_group.len(),
);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Zero-fill for consistency & safety

add_group_plugin mutates the group but does not clear the leftover bytes, unlike remove_group_plugin, approve_group_plugin, and revoke_group_plugin. Adopt the same pattern here to avoid stale data after a later shrink.

🤖 Prompt for AI Agents
In programs/mpl-core/src/plugins/group_plugins.rs around lines 108 to 113, the
code copies serialized_group into group_info but does not zero-fill the
remaining bytes, which can leave stale data. After the sol_memcpy call, add code
to zero out the rest of the group_info buffer beyond serialized_group.len() to
match the pattern used in remove_group_plugin and others, ensuring leftover
bytes are cleared for consistency and safety.

Comment on lines +216 to +226
if plugin_entry.authority_type == PluginAuthorityType::None {
if args.plugin_args.len() == 32 {
let pubkey_bytes: [u8; 32] = args.plugin_args[..32]
.try_into()
.map_err(|_| MplCoreError::InvalidPluginOperation)?;
plugin_entry.authority_type =
PluginAuthorityType::SpecificAddress(Pubkey::new_from_array(pubkey_bytes));
} else {
plugin_entry.authority_type = PluginAuthorityType::UpdateAuthority;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Ambiguous semantics for plugin_args length

Approving with a 32-byte payload implicitly sets SpecificAddress; any other length sets UpdateAuthority. Consider documenting or encoding the variant explicitly to avoid silent misconfiguration when arbitrary data > 32 bytes is supplied.

🤖 Prompt for AI Agents
In programs/mpl-core/src/plugins/group_plugins.rs around lines 216 to 226, the
current logic implicitly sets PluginAuthorityType based on the length of
plugin_args, which can cause silent misconfiguration. To fix this, explicitly
encode the authority type variant in the input data or add clear documentation
explaining this behavior. Modify the code to check for an explicit indicator of
the authority type rather than relying solely on the length of plugin_args,
ensuring that arbitrary data longer than 32 bytes does not unintentionally set
UpdateAuthority.

Comment on lines +56 to +75
if accounts.len() < 5 {
return Err(MplCoreError::MissingSystemProgram.into());
}

let authority_info = accounts
.get(0)
.ok_or::<ProgramError>(MplCoreError::MissingSigner.into())?;
let group_info = accounts
.get(1)
.ok_or::<ProgramError>(MplCoreError::GroupNotFound.into())?;
let _plugin_account_info = accounts
.get(2)
.ok_or::<ProgramError>(MplCoreError::PluginNotFound.into())?;
let plugin_program_info = accounts
.get(3)
.ok_or::<ProgramError>(MplCoreError::InvalidPlugin.into())?;
let system_program_info = accounts
.get(4)
.ok_or::<ProgramError>(MplCoreError::MissingSystemProgram.into())?;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Redundant account & potential caller confusion

_plugin_account_info (index 2) is fetched but never used, while the plugin’s program (index 3) is what gets stored in allowed_plugins.
Consequences:

  1. An extra account is needlessly required, increasing compute & CU cost.
  2. Subsequent instructions (remove_*, approve_*, …) look up the plugin by the unused account’s key, leading to a mismatch and inevitable PluginNotFound.

Either drop the unused account or store accounts[2].key in AllowedPlugin.

- let _plugin_account_info = accounts.get(2) ...?;
- let plugin_program_info  = accounts.get(3) ...?;
+ let plugin_program_info = accounts.get(2)?; // if you only need the program id

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In programs/mpl-core/src/plugins/group_plugins.rs between lines 56 and 75, the
account at index 2 (_plugin_account_info) is retrieved but never used, causing
unnecessary account requirements and confusion in plugin lookups. To fix this,
either remove the retrieval of the unused account at index 2 entirely or modify
the code to store the key of accounts[2] in AllowedPlugin instead of using the
plugin program at index 3, ensuring consistency in how plugins are referenced
across instructions.

Comment on lines +2391 to +2423
{
"name": "RemoveGroupsFromGroup",
"accounts": [
{
"name": "authority",
"isMut": false,
"isSigner": true,
"docs": [
"The parent group update authority or delegated authority"
]
},
{
"name": "parentGroup",
"isMut": true,
"isSigner": false,
"docs": [
"The parent group account"
]
}
],
"args": [
{
"name": "removeGroupsFromGroupArgs",
"type": {
"defined": "RemoveGroupsFromGroupArgs"
}
}
],
"discriminant": {
"type": "u8",
"value": 41
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

RemoveGroupsFromGroup instruction mirrors AddGroups
Accounts, args, and discriminant (41) align correctly.

Same as above: consider standardizing on group for the account name.

🤖 Prompt for AI Agents
In idls/mpl_core.json between lines 2391 and 2423, the RemoveGroupsFromGroup
instruction uses the account name "parentGroup" which should be standardized to
"group" to maintain consistency with similar instructions like AddGroups. Rename
the "parentGroup" account to "group" in the accounts array, update its
documentation accordingly to reflect it as the group account, and ensure all
references within this instruction match the new name.

Comment on lines +2358 to +2390
{
"name": "AddGroupsToGroup",
"accounts": [
{
"name": "authority",
"isMut": false,
"isSigner": true,
"docs": [
"The parent group update authority or delegated authority"
]
},
{
"name": "parentGroup",
"isMut": true,
"isSigner": false,
"docs": [
"The parent group account"
]
}
],
"args": [
{
"name": "addGroupsToGroupArgs",
"type": {
"defined": "AddGroupsToGroupArgs"
}
}
],
"discriminant": {
"type": "u8",
"value": 40
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

AddGroupsToGroup instruction is logically correct
Using parentGroup to denote the parent PDA is clear, and the args type AddGroupsToGroupArgs matches. Discriminant (40) is correct.

Consider renaming the account name parentGroup to group for naming consistency with other group-related instructions, then disambiguating in client code if needed.

🤖 Prompt for AI Agents
In idls/mpl_core.json between lines 2358 and 2390, rename the account named
"parentGroup" to "group" in the AddGroupsToGroup instruction to maintain naming
consistency with other group-related instructions. After renaming, ensure any
client code referencing this account is updated to disambiguate and correctly
use the new "group" name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant