Skip to content
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

CEP-78 #410

Merged
merged 41 commits into from
May 10, 2024
Merged

CEP-78 #410

merged 41 commits into from
May 10, 2024

Conversation

kpob
Copy link
Contributor

@kpob kpob commented Apr 24, 2024

Summary by CodeRabbit

  • New Features

    • Added new contract declarations and functionality for CEP-78 standard NFTs, including minting, burning, and transferring tokens.
    • Introduced reverse lookup operations and settings management for various NFT-related configurations.
    • Implemented event structures for NFT actions like Mint, Burn, Transfer, and Approval.
    • Added functionality to deploy and interact with CEP-78 contracts on the live network.
  • Enhancements

    • Updated Cargo.toml to include new dependencies enhancing functionality.
    • Improved dictionary storage and contract context operations by accepting byte slices for keys.
  • Bug Fixes

    • Corrected .gitignore to exclude system-specific files like .DS_Store.
  • Refactor

    • Streamlined contract container by removing and modifying method signatures and import statements.
  • Chores

    • Modified the install-cargo-odra command in the justfile to specify the stable toolchain for installation.

Copy link
Contributor

coderabbitai bot commented Apr 24, 2024

Walkthrough

The recent updates focus on enhancing functionality and efficiency in dictionary operations, enhancing the CEP-78 NFT contract capabilities, and refining the contract environment setup. Key changes include the use of byte slices for dictionary keys, new contract declarations, and updated event handling. Additionally, .gitignore was updated, and dependencies in Cargo.toml were modified to include new libraries.

Changes

Files Change Summary
.gitignore, modules/Cargo.toml Updated to include new patterns and dependencies.
benchmark/src/storage.rs, core/src/contract_context.rs Modified dictionary operations to use byte slices for keys.
core/src/args.rs, core/src/contract_container.rs Enhanced enum utilities and streamlined contract container methods.
modules/src/.../reverse_lookup.rs, modules/src/.../settings.rs, modules/src/.../token.rs, modules/src/.../utils.rs, modules/src/.../events.rs Expanded functionalities in CEP-78 NFT contract operations and settings.
examples/bin/cep78_on_livenet.rs, justfile Updated deployment commands and installation processes.

🐇✨
To code, to build, a new dawn breaks,
Byte by byte, the old forsakes.
In the realm where data streams,
A rabbit hops and softly dreams.
With each commit, a world anew,
In strings of code, our dreams we sew. 🌟🌿


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
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>.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration 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.

@kubaplas kubaplas mentioned this pull request Apr 26, 2024
@@ -49,7 +49,7 @@ pub trait ContractContext {
///
/// * `dictionary_name` - The name of the dictionary.
/// * `key` - The key to retrieve the value for.
fn get_dictionary_value(&self, dictionary_name: &str, key: &str) -> Option<Bytes>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Make sure this works by running a livenet example of cep-18 against original contract implementation.

@@ -58,7 +58,7 @@ pub trait ContractContext {
/// * `dictionary_name` - The name of the dictionary.
/// * `key` - The key to set the value for.
/// * `value` - The value to set.
fn set_dictionary_value(&self, dictionary_name: &str, key: &str, value: CLValue);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why only changed in dictionaries, what about named keys?

Copy link

github-actions bot commented May 6, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.13356 CSPR (0.15%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

Copy link

github-actions bot commented May 7, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.13482 CSPR (0.15%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

Copy link

github-actions bot commented May 7, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.0504 CSPR (0.06%)
Contract Call Entry point: get_named_key 🟢 -0.00005448 CSPR (0.02%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

Copy link

github-actions bot commented May 7, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.04788 CSPR (0.05%)
Contract Call Entry point: get_named_key 🟢 -0.00005448 CSPR (0.02%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

@kpob kpob marked this pull request as ready for review May 7, 2024 11:01
Copy link
Contributor

@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: 32

Out of diff range and nitpick comments (12)
odra-vm/src/odra_vm_contract_env.rs (1)

36-46: Consider adding documentation to these dictionary-related methods to clarify their functionalities and expected behaviors.

odra-casper/wasm-env/src/wasm_contract_env.rs (1)

33-43: Consider adding documentation to these dictionary-related methods to clarify their functionalities and expected behaviors.

modules/src/cep78/settings.rs (1)

8-45: Consider adding documentation to these storage definitions to clarify their purposes and the expected error handling.

modules/src/cep78/reverse_lookup.rs (1)

141-158: Add missing implementation details in on_mint.

The on_mint method contains a TODO comment indicating missing implementation details. It's important to address these to ensure the method functions as expected.

modules/src/cep78/metadata.rs (1)

18-23: Consider adding documentation for the single_value_storage! macro usage.

It would be beneficial for maintainability to include comments explaining the purpose and usage of this macro, especially since it's used multiple times with different parameters.

modules/src/cep78/modalities.rs (2)

9-15: Ensure documentation for WhitelistMode enum.

It would be beneficial to add comprehensive documentation for the WhitelistMode enum to explain its purpose and usage within the system, especially since it controls critical functionality.


29-37: Review default behavior and documentation for NFTHolderMode.

The default behavior for NFTHolderMode is set to Mixed, but this is not clearly documented. Adding explicit documentation about the default behavior and its implications would improve code clarity and maintainability.

modules/src/cep78/tests/mint.rs (2)

65-66: Consider removing or updating the ignored test to reflect current project requirements.

This test is marked as ignored with a comment about the proxy pattern. If this pattern is no longer relevant, consider updating or removing the test to keep the test suite clean and relevant.


164-172: Consider implementing or removing commented-out code.

There is a block of commented-out code related to reverse lookup. If this feature is not planned for immediate implementation, consider removing the code or adding a TODO with a clear timeline or conditions for implementation.

modules/src/cep78/token.rs (1)

30-34: Consider using a more descriptive name for the single_value_storage! macro.

While the macro usage is correct, the name Cep78TransferFilterContract could be more descriptive regarding its purpose in the context of the CEP-78 standard. Consider renaming it to reflect its specific role or functionality.

modules/src/cep78/tests/transfer.rs (2)

595-623: Note the missing implementation for tracking page table entries.

The actual implementation for tracking page table entries during token transfers is marked as TODO and not implemented yet. It's important to address this in future updates.


626-652: Note the missing implementation for transfers to unregistered owners.

The actual implementation for preventing transfers to unregistered owners is marked as TODO and not implemented yet. It's important to address this in future updates.

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between a460225 and 7dda987.
Files ignored due to path filters (1)
  • .DS_Store is excluded by !**/.DS_Store
Files selected for processing (45)
  • .gitignore (1 hunks)
  • benchmark/src/storage.rs (1 hunks)
  • core/src/args.rs (2 hunks)
  • core/src/contract_container.rs (3 hunks)
  • core/src/contract_context.rs (2 hunks)
  • core/src/contract_env.rs (3 hunks)
  • modules/Cargo.toml (1 hunks)
  • modules/Odra.toml (1 hunks)
  • modules/src/cep18/storage.rs (3 hunks)
  • modules/src/cep78/constants.rs (1 hunks)
  • modules/src/cep78/data.rs (1 hunks)
  • modules/src/cep78/error.rs (1 hunks)
  • modules/src/cep78/events.rs (1 hunks)
  • modules/src/cep78/metadata.rs (1 hunks)
  • modules/src/cep78/mod.rs (1 hunks)
  • modules/src/cep78/modalities.rs (1 hunks)
  • modules/src/cep78/reverse_lookup.rs (1 hunks)
  • modules/src/cep78/settings.rs (1 hunks)
  • modules/src/cep78/tests/acl.rs (1 hunks)
  • modules/src/cep78/tests/burn.rs (1 hunks)
  • modules/src/cep78/tests/costs.rs (1 hunks)
  • modules/src/cep78/tests/events.rs (1 hunks)
  • modules/src/cep78/tests/installer.rs (1 hunks)
  • modules/src/cep78/tests/metadata.rs (1 hunks)
  • modules/src/cep78/tests/mint.rs (1 hunks)
  • modules/src/cep78/tests/mod.rs (1 hunks)
  • modules/src/cep78/tests/set_variables.rs (1 hunks)
  • modules/src/cep78/tests/transfer.rs (1 hunks)
  • modules/src/cep78/tests/utils.rs (1 hunks)
  • modules/src/cep78/token.rs (1 hunks)
  • modules/src/cep78/utils.rs (1 hunks)
  • modules/src/cep78/whitelist.rs (1 hunks)
  • modules/src/lib.rs (2 hunks)
  • modules/src/storage.rs (1 hunks)
  • odra-casper/livenet-env/src/livenet_contract_env.rs (1 hunks)
  • odra-casper/rpc-client/src/casper_client.rs (1 hunks)
  • odra-casper/wasm-env/src/host_functions.rs (3 hunks)
  • odra-casper/wasm-env/src/wasm_contract_env.rs (1 hunks)
  • odra-schema/src/custom_type.rs (2 hunks)
  • odra-schema/src/ty.rs (2 hunks)
  • odra-vm/src/odra_vm_contract_env.rs (1 hunks)
  • odra-vm/src/vm/odra_vm.rs (3 hunks)
  • odra-vm/src/vm/odra_vm_state.rs (1 hunks)
  • odra-vm/src/vm/storage.rs (6 hunks)
  • odra/src/lib.rs (1 hunks)
Files not summarized due to errors (1)
  • odra-vm/src/odra_vm_contract_env.rs: Error: Server error. Please try again later.
Files not reviewed due to errors (2)
  • modules/src/cep78/tests/costs.rs (no review received)
  • odra-casper/wasm-env/src/host_functions.rs (no review received)
Files skipped from review due to trivial changes (3)
  • .gitignore
  • modules/src/cep78/constants.rs
  • odra/src/lib.rs
Additional comments not posted (107)
modules/src/cep78/mod.rs (1)

3-15: All module declarations appear to be correctly structured and consistent with Rust's module system.

modules/src/lib.rs (2)

4-4: The recursion limit has been set to "256". Ensure this is sufficient for the complexity of the macros used in this project.


11-11: The cep78 module has been correctly declared and is consistent with the project's structure.

modules/Odra.toml (1)

25-36: New contract declarations for cep78 have been added correctly and are consistent with the project's structure.

benchmark/src/storage.rs (2)

41-41: The method set_dictionary_value has been updated to use byte slices for keys, aligning with the project's performance optimization goals.


47-47: The method get_dictionary_value has been updated to use byte slices for keys. Ensure that all calls to this method across the project have been updated accordingly.

Verification successful

The output from the executed script indicates that all instances of get_dictionary_value across various files in the codebase are using byte slices for keys, as required by the updated method signature. Each call to get_dictionary_value correctly passes a byte slice (&[u8]) as the key parameter. This confirms that the necessary updates have been made consistently across the project.

Conclusion:
The verification confirms that all calls to get_dictionary_value in the project have been correctly updated to use byte slices for keys. There are no instances where the old signature is used.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that all calls to `get_dictionary_value` use byte slices for keys.

# Test: Search for the function usage with old signature. Expect: No occurrences.
rg --type rust $'get_dictionary_value\\([^,]+, [^&]'

Length of output: 1382

modules/Cargo.toml (1)

14-23: New dependencies (serde, serde_json, serde-json-wasm, base16, once_cell, and blake2) have been added correctly. Ensure that these dependencies are necessary for the project's functionality and check for potential version conflicts.

modules/src/cep78/tests/set_variables.rs (2)

11-39: The unit test only_installer_should_be_able_to_toggle_allow_minting is well-structured and covers the scenario adequately. Ensure that the error handling and event emission are correctly implemented.


50-64: The unit test installer_should_be_able_to_toggle_operator_burn_mode correctly tests the functionality. Ensure that the event emission is correctly implemented and matches the expected format.

modules/src/cep78/tests/mod.rs (2)

25-31: The utility function default_args_builder is correctly implemented and provides a clear, reusable way to build default arguments for tests.


33-38: The static variable TEST_CUSTOM_METADATA is correctly implemented using Lazy for efficient initialization. Ensure that the data it contains is accurate and relevant to the tests.

modules/src/cep78/whitelist.rs (2)

25-28: The method clear in Cep78ACLWhitelist correctly implements the functionality to clear the ACL whitelist. Ensure that this method is called appropriately within the system to maintain correct state management.


62-75: The method update in ACLWhitelist handles the updating of whitelist entries based on the mode. Ensure that the error handling (InvalidWhitelistMode) is correctly triggered under the appropriate conditions.

modules/src/cep78/tests/utils.rs (2)

48-63: LGTM! Efficient use of filter_map to retrieve specific gas costs.


65-74: LGTM! Consistent and efficient retrieval of deployment gas costs.

modules/src/cep78/tests/events.rs (1)

59-82: LGTM! Proper setup and validation of conditions in the test for no event recording.

modules/src/cep78/events.rs (7)

3-18: LGTM! Well-defined event structure and constructor for Mint.


21-35: LGTM! Consistent event structure and constructor for Burn.


37-52: LGTM! Consistent event structure and constructor for Approval.


54-64: LGTM! Consistent event structure and constructor for ApprovalRevoked.


66-76: LGTM! Consistent event structure and constructor for ApprovalForAll.


78-88: LGTM! Consistent event structure and constructor for RevokedForAll.


90-112: LGTM! Well-defined event structure and constructor for Transfer, including appropriate handling of optional fields.

odra-vm/src/odra_vm_contract_env.rs (2)

36-46: LGTM! Correct implementation of dictionary operations in the VM environment.


36-46: LGTM! Correct implementation of various contract-related functionalities in the VM environment.

odra-casper/wasm-env/src/wasm_contract_env.rs (3)

33-43: LGTM! Correct implementation of dictionary operations in the Wasm environment.


33-43: LGTM! Correct delegation of hashing operation to host functions in the Wasm environment.


33-43: LGTM! Correct implementation of various contract-related functionalities in the Wasm environment.

modules/src/cep78/settings.rs (2)

8-45: LGTM! Correct use of single_value_storage macro for defining various settings with appropriate error handling.


59-130: LGTM! Well-implemented methods for managing settings with clear interfaces and optimized performance.

odra-schema/src/custom_type.rs (2)

54-54: Addition of Bytes to schema custom types is appropriate for handling byte arrays.


55-55: Inclusion of URef in schema custom types is crucial for referencing blockchain data.

core/src/contract_context.rs (3)

52-52: Update to accept byte slices as dictionary keys aligns with performance optimization efforts.

Verification successful

The verification of the get_dictionary_value method's integration with existing contracts has been successfully completed. All occurrences in the codebase use byte slices for keys, consistent with the updated method signature. This confirms that the method's update aligns with the project's performance optimization efforts and has been correctly integrated across various components of the system.

  • Files and locations verified:
    • odra-vm/src/odra_vm_contract_env.rs
    • odra-casper/wasm-env/src/wasm_contract_env.rs
    • odra-casper/wasm-env/src/host_functions.rs
    • odra-casper/rpc-client/src/casper_client.rs
    • odra-casper/livenet-env/src/livenet_contract_env.rs
    • modules/src/storage.rs
    • modules/src/cep78/tests/transfer.rs
    • modules/src/cep78/metadata.rs
    • modules/src/cep18/storage.rs
    • core/src/contract_env.rs
    • benchmark/src/storage.rs
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify integration of `get_dictionary_value` with existing contracts.

# Test: Search for the function usage. Expect: Only occurances with byte slice keys.
rg --type rust $'get_dictionary_value'

Length of output: 1974


61-61: Update to accept byte slices as dictionary keys in set_dictionary_value is consistent with performance optimization efforts.

Verification successful

The verification process confirms that the updated set_dictionary_value method is correctly integrated across the codebase. All instances use byte slices for dictionary keys, including the usage where key is derived from the compound_key function, which returns a byte array that is compatible as a byte slice.

  • odra-vm/src/odra_vm_contract_env.rs
  • odra-casper/wasm-env/src/wasm_contract_env.rs
  • odra-casper/wasm-env/src/host_functions.rs
  • odra-casper/livenet-env/src/livenet_contract_env.rs
  • modules/src/storage.rs
  • modules/src/cep78/metadata.rs
  • modules/src/cep18/storage.rs
  • benchmark/src/storage.rs
  • core/src/contract_env.rs
  • core/src/contract_context.rs
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify integration of `set_dictionary_value` with existing contracts.

# Test: Search for the function usage. Expect: Only occurances with byte slice keys.
rg --type rust $'set_dictionary_value'

Length of output: 1715



Script:

#!/bin/bash
# Description: Verify the type of `key` in the suspicious usage of `set_dictionary_value`.

# Test: Check the type of `key` in the specific file where it's used directly.
rg --type rust 'let key =' modules/src/storage.rs

Length of output: 193



Script:

#!/bin/bash
# Description: Verify the return type of `compound_key` used in defining `key`.

# Test: Search for the definition of `compound_key` to determine its return type.
rg --type rust 'fn compound_key' modules/src/storage.rs

Length of output: 157


63-67: Addition of remove_dictionary method enhances storage management capabilities.

Verification successful

The verification of the remove_dictionary method's integration across the project shows that it is implemented and used consistently in various parts of the codebase. This includes multiple contract environments and direct usage within contract logic, indicating a successful integration.

  • livenet_contract_env.rs, wasm_contract_env.rs, odra_vm_contract_env.rs: Implementations in different environments.
  • host_functions.rs, odra_vm_state.rs: Core functionality implementations.
  • whitelist.rs: Usage in contract logic.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify integration of `remove_dictionary` with existing contracts.

# Test: Search for the function usage. Expect: Proper usage across the project.
rg --type rust $'remove_dictionary'

Length of output: 1254

odra-casper/livenet-env/src/livenet_contract_env.rs (3)

42-42: Update to handle byte slices in get_dictionary_value aligns with project standards and the error handling is crucial for live network environments.


50-50: Update to handle byte slices in set_dictionary_value aligns with project standards and the error handling is crucial for live network environments.


54-57: Addition of remove_dictionary with error handling to prevent execution without a deploy is crucial for maintaining state integrity in live network environments.

modules/src/storage.rs (5)

1-23: Update to single_value_storage macro to include error handling enhances user feedback and error management.


39-59: Update to key_value_storage macro to handle dictionary keys as byte slices aligns with performance optimization efforts.


61-93: Addition of base64_encoded_key_value_storage macro extends key-value storage capabilities to handle non-ASCII or binary data, enhancing flexibility.


95-134: Addition of compound_key_value_storage macro allows for handling complex data structures with compound keys, enhancing data modeling capabilities.


136-146: compound_key function uses the environment's hash function to ensure consistent key handling, crucial for the integrity of compound key operations.

odra-schema/src/ty.rs (1)

162-166: Inclusion of ContractHash as a NamedCLType is essential for representing contract hashes in type-safe operations.

modules/src/cep78/data.rs (4)

28-36: Addition of add method to Cep78TokenCounter enhances token management by allowing dynamic increments of the minted tokens count.


65-85: init method in CollectionData properly sets up initial state with checks against zero or excessive token supply, crucial for maintaining token system integrity.


117-137: Methods for managing token ownership, issuance, and counts in CollectionData are well-implemented, covering essential functionalities with necessary checks and balances.


150-157: mark_burnt and is_burnt methods provide essential management of token burning status, aligning with token lifecycle needs.

core/src/args.rs (1)

39-45: Addition of unwrap_or method to Maybe enum enhances handling of optional values by providing a flexible, error-tolerant way to unwrap.

modules/src/cep78/error.rs (1)

1-173: Comprehensive error definitions in CEP78Error are crucial for robust error handling and user feedback in CEP-78 operations.

modules/src/cep18/storage.rs (2)

129-129: Ensure consistent error handling for get_dictionary_value.

Verification successful

Consistent Error Handling for get_dictionary_value Verified

The review of the get_dictionary_value function across various modules and files in the codebase shows a consistent pattern in error handling. The function typically returns an Option<Bytes>, and the handling of this optional value is consistent, primarily using methods like unwrap_or_default() or similar error-resilient methods. This ensures that the function's usage does not lead to unhandled exceptions or panics due to missing values.

Here are some key observations from the codebase:

  • In modules/src/storage.rs, the function is used with unwrap_or_default(), which provides a default value in case of None.
  • In modules/src/cep18/storage.rs, the function is also used with unwrap_or_default() for both BALANCES_KEY and ALLOWANCES_KEY.
  • In modules/src/cep78/metadata.rs, it uses unwrap_or_revert_with(), which is another form of error handling that ensures errors are managed explicitly.

These usages confirm that the error handling around get_dictionary_value is handled appropriately and consistently across the project.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify consistent error handling for `get_dictionary_value` across the project.

# Test: Search for the function usage. Expect: Consistent error handling.
rg --type rust $'get_dictionary_value'

Length of output: 1974



Script:

#!/bin/bash
# Description: Further investigate how the returned Option<Bytes> from get_dictionary_value is handled in each case.

# Test: Search for the handling of the function's return value in each file where it's used.
rg --type rust -C 3 $'get_dictionary_value'

Length of output: 7973


171-171: Ensure consistent error handling for set_dictionary_value in allowances context.

Verification successful

The examination of the set_dictionary_value usage in both the allowances and balances contexts within the modules/src/cep18/storage.rs file reveals a consistent approach. Both usages directly invoke the function without any surrounding explicit error handling mechanisms. This suggests that error handling is either managed internally within the function or by the environment's error handling mechanisms, consistently across different contexts.

  • Allowances Context: Direct setting of allowances without explicit error handling.
  • Balances Context: Direct setting of balances without explicit error handling.

Given this consistency, the error handling for set_dictionary_value in the allowances context appears to be in line with other usages within the same module.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify consistent error handling for `set_dictionary_value` in allowances context across the project.

# Test: Search for the function usage. Expect: Consistent error handling.
rg --type rust $'set_dictionary_value'

Length of output: 1715



Script:

#!/bin/bash
# Description: Inspect error handling around `set_dictionary_value` usage in allowances context.

# Search for error handling mechanisms around the usage of `set_dictionary_value` in the allowances context.
rg --type rust -C 5 "set_dictionary_value\(.*ALLOWANCES_KEY" modules/src/cep18/storage.rs

Length of output: 539


Script:

#!/bin/bash
# Description: Inspect error handling around `set_dictionary_value` usage in balances context for comparison.

# Search for error handling mechanisms around the usage of `set_dictionary_value` in the balances context.
rg --type rust -C 5 "set_dictionary_value\(.*BALANCES_KEY" modules/src/cep18/storage.rs

Length of output: 480

modules/src/cep78/tests/installer.rs (1)

107-112: Verify that the error handling for re-burning a previously burnt token is consistent across the project.

core/src/contract_env.rs (1)

107-110: Ensure consistent error handling for get_dictionary_value.

Verification successful

Based on the search results, the function get_dictionary_value is used across multiple files and modules in the project. Most of these usages return an Option<Bytes>, which suggests a pattern of using Rust's option type for error handling—returning None in case of an error. However, to ensure that error handling is indeed consistent (e.g., no unhandled errors, no unnecessary error logs, or deviations in error handling strategy), a deeper examination of each usage context is necessary.

To proceed, I will generate additional verification scripts to inspect the implementation and usage of get_dictionary_value in a few key files to confirm the consistency of error handling.


The examination of the get_dictionary_value function across different files in the project reveals a consistent pattern of error handling. The function typically returns an Option<Bytes>, where None is returned in case of an error, such as when a value is not found. This pattern is observed across various implementations in different environments, such as wasm-env, rpc-client, and core.

In the detailed implementations, errors are handled by reverting the operation or returning None, without any unhandled exceptions or inconsistent error handling mechanisms. This confirms that the error handling for the get_dictionary_value function is consistent across the project.

Therefore, the review comment regarding ensuring consistent error handling for get_dictionary_value has been verified and found to be correctly implemented across the codebase.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify consistent error handling for `get_dictionary_value` across the project.

# Test: Search for the function usage. Expect: Consistent error handling.
rg --type rust $'get_dictionary_value'

Length of output: 1974



Script:

#!/bin/bash
# Inspect error handling in wasm-env
cat odra-casper/wasm-env/src/wasm_contract_env.rs
cat odra-casper/wasm-env/src/host_functions.rs

# Inspect error handling in rpc-client
cat odra-casper/rpc-client/src/casper_client.rs

# Inspect error handling in core environment
cat core/src/contract_env.rs

Length of output: 66677

modules/src/cep78/utils.rs (1)

76-80: Check for potential data races in burn method.

The burn method accesses shared state (nft_contract) which might lead to data races in a concurrent environment. Verify that appropriate locking mechanisms are used.

odra-vm/src/vm/storage.rs (1)

76-86: Validate inputs in remove_dict to prevent potential errors.

The remove_dict method removes a dictionary without validating the existence of the dictionary key. Consider adding checks to prevent errors in case the key does not exist.

Verification successful

The review comment regarding the lack of input validation in the remove_dict method is accurate. The method currently removes a dictionary key without checking its existence, which could lead to potential errors if the key does not exist. It is advisable to implement checks to ensure the dictionary key exists before attempting to remove it.

  • File: odra-vm/src/vm/storage.rs
  • Method: remove_dict
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check for input validation in remove_dict method.

# Test: Search for validation patterns. Expect: Validation code before removing dictionary.
rg --type rust 'remove_dict' odra-vm/src/vm/storage.rs

Length of output: 226

modules/src/cep78/metadata.rs (3)

55-66: Ensure proper error handling for dictionary operations.


98-104: Validate JSON schema parsing error handling.

Verification successful

The JSON schema parsing error handling has been verified across two occurrences in the codebase. Both instances correctly handle errors by reverting the operation with CEP78Error::InvalidJsonSchema, ensuring that contract installation fails as expected upon encountering a parsing error. This aligns with the requirements specified in the review comment.

  • First occurrence: modules/src/cep78/metadata.rs around line 102
  • Second occurrence: modules/src/cep78/metadata.rs around line 106
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Ensure that JSON schema parsing errors are correctly handled and lead to contract installation failure.

# Test: Search for JSON schema parsing in contract installation. Expect: Correct error handling.
rg --type rust $'serde_json_wasm::from_str::<CustomMetadataSchema>'

Length of output: 299



Script:

#!/bin/bash
# Description: Verify the error handling for the second occurrence of JSON schema parsing.
# Focus: Check if the error leads to a contract installation failure.

# Extract the surrounding code for the second occurrence of JSON schema parsing.
rg --type rust -C 5 'serde_json_wasm::from_str::<CustomMetadataSchema>\(&self.json_schema.get\(\)\)' modules/src/cep78/metadata.rs

Length of output: 525


241-307: Check the implementation of get_metadata_schema.

Verification successful

The provided shell script output shows two occurrences of the get_metadata_schema method within the metadata.rs file. One is the definition of the method itself, and the other is its usage where a token_schema is being retrieved. This aligns with the expected behavior of the method being used within its module.

However, the script was intended to verify the correct implementation and error handling within the get_metadata_schema method. The output does not provide detailed insights into how error handling is implemented, particularly in the CustomValidated case where JSON parsing errors are supposed to revert the operation.

To further verify the error handling, particularly how the method handles potential errors in the CustomValidated case, we need to inspect the error handling logic more closely. This involves checking how errors from the serde_json_wasm::from_str function are managed and ensuring that they correctly trigger the revert operation with the appropriate environment.

Given the current information, we need to delve deeper into the error handling specifics of the CustomValidated case.


The new script output provides detailed context around the error handling in the CustomValidated case of the get_metadata_schema method. It shows that the method attempts to parse a JSON string into a CustomMetadataSchema object. If parsing fails, it triggers an error (CEP78Error::InvalidJsonSchema) and reverts the operation using unwrap_or_revert with the environment provided by self.env().

This error handling mechanism is crucial for ensuring that only valid JSON schemas are processed, and any invalid schemas result in a controlled failure, preventing further execution with potentially corrupted data.

Given this detailed insight into the error handling logic, it appears that the implementation of get_metadata_schema in the CustomValidated case is correctly handling errors as expected. The method properly manages JSON parsing errors and ensures that operations are reverted in case of an error, which aligns with robust error handling practices in critical operations like schema validation.

Based on this information, the implementation of the get_metadata_schema method, particularly its error handling, is verified to be correct.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the correct implementation of `get_metadata_schema` method, especially the error handling and schema retrieval logic.

# Test: Search for the usage of `get_metadata_schema`. Expect: Correct implementation and error handling.
rg --type rust $'get_metadata_schema'

Length of output: 239



Script:

#!/bin/bash
# Description: Verify the error handling in the `CustomValidated` case of the `get_metadata_schema` method.

# Test: Search for the error handling logic in the `CustomValidated` case.
rg --type rust --context 5 'CustomValidated' modules/src/cep78/metadata.rs

Length of output: 2184

modules/src/cep78/tests/acl.rs (5)

17-33: Ensure comprehensive testing for ACL whitelist functionality.

Verification successful

The review comment regarding the comprehensive testing of ACL whitelist functionality appears to be addressed adequately. The codebase demonstrates extensive use of the acl_white_list across various test files, covering different scenarios and types of whitelists (contract, account, mixed). This suggests a thorough approach to testing the ACL whitelist functionality in different contexts.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the ACL whitelist functionality is comprehensively tested, especially the scenarios involving locked and unlocked modes.

# Test: Search for tests covering ACL whitelist scenarios. Expect: Comprehensive coverage.
rg --type rust $'acl_white_list'

Length of output: 2234


39-58: Check error handling in minting mode validation.

Verification successful

The review comment requested verification of the error handling for the minting mode validation when an ACL whitelist is provided. The script executed searched for occurrences of InvalidMintingMode in the Rust files of the codebase.

Analysis of Script Results:

  • The error InvalidMintingMode is referenced in several files:
    • token.rs: The error is used in a method to revert an operation.
    • acl.rs: The error is correctly used in the test to check the robustness of the error handling.
    • modalities.rs: The error is returned in some conditional logic.
    • error.rs: The error is defined here with a specific error code.

Conclusion:

The error handling for the minting mode validation appears to be implemented across multiple files and is used consistently in the context of ACL whitelist provision. The test in acl.rs specifically checks for this error when the minting mode is not set correctly, aligning with the intended functionality described in the review comment.

Given the evidence from the script output, the error handling for the minting mode validation when an ACL whitelist is provided seems robust and correctly implemented.


Error Handling in Minting Mode Validation Verified

  • The error InvalidMintingMode is appropriately triggered and handled in the test scenario provided in acl.rs.
  • The usage of this error across the codebase supports its robust implementation.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Ensure that the error handling for incorrect minting mode when ACL whitelist is provided is robust.

# Test: Search for error handling in minting mode validation. Expect: Robust error handling.
rg --type rust $'InvalidMintingMode'

Length of output: 343


74-89: Validate tests for public mode with empty locked whitelist.

Verification successful

The output from the executed script confirms that the test function should_allow_installation_of_contract_with_empty_locked_whitelist_in_public_mode() and its helper function should_allow_installation_of_contract_with_empty_locked_whitelist_in_public_mode_with_holder_mode() are present in the codebase. These functions are designed to test the installation of a contract in public mode with an empty locked whitelist, covering different NFTHolderMode scenarios (Accounts, Contracts, Mixed).

Given this information, it appears that the tests for public mode with an empty locked whitelist are implemented as expected, covering all necessary scenarios as outlined in the provided code snippet.


Final Response:

The tests for public mode with an empty locked whitelist are correctly implemented and cover all necessary scenarios as per the provided code snippet and the search results from the repository.

  • should_allow_installation_of_contract_with_empty_locked_whitelist_in_public_mode() is the main test function.
  • should_allow_installation_of_contract_with_empty_locked_whitelist_in_public_mode_with_holder_mode() is used to test different holder modes.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the tests for public mode with an empty locked whitelist are correctly implemented and cover all necessary scenarios.

# Test: Search for tests related to public mode with empty locked whitelist. Expect: Correct implementation and coverage.
rg --type rust $'public_mode'

Length of output: 682


112-144: Review ACL whitelist and minting functionality test.

Verification successful

The test in modules/src/cep78/tests/acl.rs appears to accurately reflect the intended behavior of the ACL whitelist and minting functionality. The test ensures that a user listed in the ACL whitelist can successfully mint a token and verifies the ownership of the minted token, which aligns with the expected behavior of such a feature.

  • The test checks if the user is whitelisted.
  • It sets the user as the caller and performs the minting.
  • It verifies that the minted token is owned by the correct user.

This test setup and execution seem to correctly validate the ACL whitelist and minting functionality as intended.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Review the test covering ACL whitelist and minting functionality to ensure it accurately reflects the intended behavior.

# Test: Search for tests covering ACL whitelist and minting functionality. Expect: Accurate reflection of intended behavior.
rg --type rust $'acl_white_list'

Length of output: 2234


146-177: Examine error handling for unlisted accounts in minting.

Verification successful

The review comment requested verification of the error handling for scenarios where unlisted accounts attempt to mint, focusing on the robustness and correctness of the implementation. The provided script searched for occurrences of InvalidMinter in the Rust files, which is the error expected to be thrown when an unlisted account attempts to mint.

Analysis of Script Output:

  • The error InvalidMinter is defined in modules/src/cep78/error.rs.
  • It is used in modules/src/cep78/token.rs in two places, indicating that the error is actively thrown in scenarios likely related to minting by unlisted accounts.
  • The test file modules/src/cep78/tests/acl.rs contains two instances where InvalidMinter is expected as an error output, which aligns with the test scenario described in the review comment.
  • Another test in modules/src/cep78/tests/mint.rs also expects this error, suggesting that the error handling is consistently tested across different scenarios.

Conclusion:

The error handling for unlisted accounts attempting to mint appears to be robust and correctly implemented. The error InvalidMinter is not only defined but also actively used in relevant parts of the codebase, and its handling is covered in multiple test cases. This indicates a thorough approach to ensuring that unlisted accounts cannot mint, and if they attempt to, the system correctly identifies and handles the error.

Given this information, the error handling for unlisted accounts in minting has been verified as robust and correctly implemented.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Examine the error handling for scenarios where unlisted accounts attempt to mint, ensuring it is robust and correctly implemented.

# Test: Search for error handling related to unlisted accounts in minting. Expect: Robust and correct implementation.
rg --type rust $'InvalidMinter'

Length of output: 570

modules/src/cep78/modalities.rs (3)

63-79: Check implementation and usage of MintingMode.

Verification successful

The implementation and usage of MintingMode across the project appear to be consistent and correctly integrated. It is used in various modules for settings configurations, testing scenarios, and conditional logic in token management. The handling of related errors also suggests robust error management practices are in place.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check the implementation and usage of `MintingMode` to ensure it aligns with the system's requirements and is used consistently across the project.

# Test: Search for usage of `MintingMode`. Expect: Consistent and correct implementation.
rg --type rust $'MintingMode'

Length of output: 5806


94-109: Validate the addition of NFTKind enum.

The addition of the NFTKind enum is well-implemented and serves to clarify the types of NFTs handled by the system. This is a positive change that enhances the modularity and clarity of the codebase.


180-196: Examine OwnershipMode for potential issues.

Verification successful

The output from the rg command shows extensive usage of the OwnershipMode enum across various files in the cep78 module. This enum is used in settings, token handling, tests, and other utility functions, indicating its integral role in the system's functionality related to NFT ownership management.

Key Observations:

  1. Enum Variants Usage: The enum variants (Minter, Assigned, Transferable) are actively used in conditional checks and function parameters across the module. This suggests that the enum is well-integrated into the logic of the system.
  2. Error Handling: There are specific error cases (InvalidOwnershipMode, MissingOwnershipMode) handled in the system, which shows that there are safeguards against incorrect usage or setup of ownership modes.
  3. Test Coverage: The enum is used in various test scenarios, particularly with the Transferable mode being tested extensively. This indicates an emphasis on ensuring that transferable ownership functions as expected.

Conclusion:

The OwnershipMode enum appears to be correctly implemented and extensively used throughout the cep78 module with appropriate error handling and test coverage. There are no immediate signs of misalignment with system requirements or potential issues based on the current usage patterns observed in the output.

Given the thorough integration and testing of the OwnershipMode enum, as well as the handling of potential errors, it seems that the enum is functioning as intended within the system's architecture.


Based on the analysis, the review comment has been addressed adequately:

  • The enum is well-utilized and integrated into the system.
  • There are mechanisms in place to handle errors related to ownership modes.
  • Extensive testing is performed, especially on the Transferable mode.

Therefore, I conclude that there are no issues with the OwnershipMode enum as per the current implementation and usage within the codebase.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Examine the `OwnershipMode` enum for any potential issues or misalignments with the system's requirements.

# Test: Search for usage and implications of `OwnershipMode`. Expect: No issues or misalignments.
rg --type rust $'OwnershipMode'

Length of output: 10507

modules/src/cep78/tests/metadata.rs (16)

29-56: Ensure proper handling of immutable metadata updates.

This test correctly checks that an attempt to update metadata in immutable mode results in a ForbiddenMetadataUpdate error, aligning with expected behavior.


58-67: Validate deployment in mutable mode.

The test verifies that deploying a contract with mutable metadata is successful, which is crucial for dynamic metadata management.


69-97: Check handling of malformed metadata.

This test ensures that the contract correctly rejects malformed metadata updates with a FailedToParse721Metadata error, which is essential for data integrity.


99-130: Verify metadata update restrictions based on ownership.

The test confirms that only the token owner can update the metadata, which is a critical security feature to prevent unauthorized changes.


133-230: Enhance testing for valid metadata updates.

This comprehensive test function covers various metadata kinds and identifier modes, ensuring that valid updates are processed correctly. It also checks for the emission of the MetadataUpdated event, which is important for tracking changes.


232-238: Simplify test for NFT721 metadata updates.

This test is a specific instance of the generic should_allow_update_for_valid_metadata_based_on_kind function, focusing on the NFT721 metadata kind. It's good to have specific tests for clarity and ease of understanding.


240-246: Simplify test for CEP78 metadata updates.

Similar to the previous comment, this test focuses on the CEP78 metadata kind, ensuring that the contract behaves as expected for this specific type of metadata.


248-254: Simplify test for custom validated metadata updates.

This test ensures that custom validated metadata can be updated correctly, which is crucial for contracts that need to enforce specific validation rules on their metadata.


256-281: Ensure retrieval of metadata using token ID.

This test checks that metadata can be correctly retrieved using a token ID, which is fundamental for any NFT-related operations.


283-312: Ensure retrieval of metadata using token hash.

This test verifies that metadata can be retrieved using a token hash, which is important for operations that use hash-based identifiers.


314-346: Prevent duplicate minting using token hash.

The test ensures that the contract prevents duplicate minting using the same token hash, which is crucial to maintain the uniqueness of tokens.


348-377: Ensure retrieval of metadata using custom token hash.

This test checks that metadata can be retrieved using a custom token hash, which is important for flexibility in handling different types of token identifiers.


379-415: Prevent duplicate minting using custom token hash identifier.

This test ensures that minting with a custom token hash identifier cannot be done more than once, which is essential for maintaining token uniqueness and integrity.


418-429: Clarify requirement for valid JSON schema in custom validated kind.

This test is commented out, suggesting it's either in development or deprecated. If active, it should validate the necessity of a JSON schema for custom validated metadata kinds.


431-448: Validate JSON schema requirement for custom validated metadata.

This test correctly checks that deploying a contract without a required JSON schema for custom validated metadata results in an error, which is crucial for ensuring that metadata meets specified standards.


450-479: Confirm non-requirement of JSON schema for non-custom validated kinds.

This function tests that a JSON schema is not required for metadata kinds other than custom validated, which is important for flexibility in metadata handling.

odra-vm/src/vm/odra_vm.rs (3)

179-182: LGTM! The method set_dict_value correctly handles the byte slice keys and CLValue conversion.


187-193: LGTM! The method remove_dictionary correctly handles the removal of dictionaries from the global state.


199-204: LGTM! The method get_dict_value correctly handles the byte slice keys and error management.

odra-casper/rpc-client/src/casper_client.rs (1)

129-132: LGTM! The method get_dictionary_value correctly handles the byte slice keys and error management.

modules/src/cep78/token.rs (1)

297-328: Verify the logic for checking token ownership in the burn function.

The burn function includes logic to check if the caller is the owner or an approved operator of the token. Ensure that this logic correctly handles all cases, especially when the token owner is a contract or another non-standard account type. Consider adding tests to cover these scenarios.

modules/src/cep78/tests/transfer.rs (19)

22-57: Ensure consistent error handling for transfer operations.


59-115: Validate event emission correctness in transfer scenarios.


177-223: Ensure correct handling of revocation events.

This function correctly handles the revocation of token transfer approvals and checks for the appropriate event emission.


238-261: Validate error handling for approval restrictions.

This function correctly handles scenarios where approving transfers is disallowed due to ownership mode restrictions.


263-305: Check for consistency in approval and transfer logic.

This function correctly implements the logic for token transfers under various conditions, including using an approved account.


321-377: Ensure robust testing for repeated transfer attempts by the same account.

This function robustly tests the scenario where a previously approved account attempts to transfer a token twice, correctly handling the expected error.


379-437: Validate error handling for transfer attempts using revoked approval.

This function correctly handles scenarios where a token transfer is attempted using a revoked approval hash, ensuring robust error handling.


457-493: Ensure correct whitelisting and transfer logic between contracts and accounts.

This function correctly implements the logic for transferring tokens between contracts and accounts, including checks for whitelisting.


495-527: Validate error handling for unauthorized transfer attempts.

This function correctly handles scenarios where a transfer attempt is made by a caller who is not the owner of the token.


530-554: Ensure correct handling of token transfers in hash identifier mode.

This function correctly implements the logic for transferring tokens in hash identifier mode, using the hash as the identifier.


557-592: Validate error handling for unauthorized transfer attempts by non-approved contracts.

This function correctly handles scenarios where a non-approved contract attempts to transfer a token, ensuring robust error handling.


655-698: Validate the logic for transfer-only reporting in token transfers.

This function correctly implements the logic for transferring tokens with transfer-only reporting, ensuring that the balances are correctly updated.


701-719: Ensure robust error handling for self-approval attempts by owners.

This function correctly handles scenarios where an owner attempts to approve itself for a transfer, ensuring robust error handling.


722-744: Validate error handling for self-approval attempts by operators.

This function correctly handles scenarios where an operator attempts to approve itself for a transfer, ensuring robust error handling.


748-766: Ensure robust error handling for global self-approval attempts by owners.

This function correctly handles scenarios where an owner attempts to set a global approval for itself, ensuring robust error handling.


769-840: Validate the handling of transfer filter contract modes in token transfers.

This function correctly implements the logic for handling different settings of a transfer filter contract in token transfers, ensuring that transfers are correctly allowed or denied based on the contract's return value.


843-867: Validate error handling for unauthorized transfer attempts from contracts in package operator mode.

This function correctly handles scenarios where a transfer from a contract is attempted without an operator in package operator mode, ensuring robust error handling.


876-904: Ensure correct handling of transfers from contracts with an operator in package operator mode.

This function correctly implements the logic for allowing transfers from contracts when an operator is set in package operator mode, ensuring that the transfers are correctly handled.


911-946: Validate the logic for package operator approvals in package operator mode.

This function correctly implements the logic for allowing package operators to approve transfers in package operator mode, ensuring that the approvals are correctly handled.

Comment on lines 69 to 183
acl_white_list: Maybe<Vec<Address>>,
json_schema: Maybe<String>,
burn_mode: Maybe<BurnMode>,
operator_burn_mode: Maybe<bool>,
owner_reverse_lookup_mode: Maybe<OwnerReverseLookupMode>,
events_mode: Maybe<EventsMode>,
transfer_filter_contract_contract: Maybe<Address>,
additional_required_metadata: Maybe<Vec<NFTMetadataKind>>,
optional_metadata: Maybe<Vec<NFTMetadataKind>>
) {
let installer = self.caller();
let minting_mode = minting_mode.unwrap_or_default();
let owner_reverse_lookup_mode = owner_reverse_lookup_mode.unwrap_or_default();
let acl_white_list = acl_white_list.unwrap_or_default();
let whitelist_mode = whitelist_mode.unwrap_or_default();
let json_schema = json_schema.unwrap_or_default();
let is_whitelist_empty = acl_white_list.is_empty();

// Revert if minting mode is not ACL and acl list is not empty
if MintingMode::Acl != minting_mode && !is_whitelist_empty {
self.revert(CEP78Error::InvalidMintingMode)
}

// Revert if minting mode is ACL or holder_mode is contracts and acl list is locked and empty
if MintingMode::Acl == minting_mode
&& is_whitelist_empty
&& WhitelistMode::Locked == whitelist_mode
{
self.revert(CEP78Error::EmptyACLWhitelist)
}

// NOTE: It is commented out to allow having mutable metadata with hash identifier.
// NOTE: It's left for future reference.
// if identifier_mode == NFTIdentifierMode::Hash
// && metadata_mutability == MetadataMutability::Mutable
// {
// self.revert(CEP78Error::InvalidMetadataMutability)
// }

if ownership_mode == OwnershipMode::Minter
&& minting_mode == MintingMode::Installer
&& owner_reverse_lookup_mode == OwnerReverseLookupMode::Complete
{
self.revert(CEP78Error::InvalidReportingMode)
}

// Check if schema is missing before checking its validity
if nft_metadata_kind == NFTMetadataKind::CustomValidated && json_schema.is_empty() {
self.revert(CEP78Error::MissingJsonSchema)
}

// OwnerReverseLookup TransfersOnly mode should be Transferable
if OwnerReverseLookupMode::TransfersOnly == owner_reverse_lookup_mode
&& OwnershipMode::Transferable != ownership_mode
{
self.revert(CEP78Error::OwnerReverseLookupModeNotTransferable)
}

if ownership_mode != OwnershipMode::Transferable
&& transfer_filter_contract_contract.is_some()
{
self.revert(CEP78Error::TransferFilterContractNeedsTransferableMode)
}

self.data.init(
collection_name,
collection_symbol,
total_token_supply,
installer
);
self.settings.init(
allow_minting.unwrap_or(true),
minting_mode,
ownership_mode,
nft_kind,
holder_mode.unwrap_or_default(),
burn_mode.unwrap_or_default(),
events_mode.unwrap_or_default(),
operator_burn_mode.unwrap_or_default()
);

self.reverse_lookup
.init(owner_reverse_lookup_mode, receipt_name);

self.whitelist.init(acl_white_list.clone(), whitelist_mode);

self.metadata.init(
nft_metadata_kind,
additional_required_metadata,
optional_metadata,
metadata_mutability,
identifier_mode,
json_schema
);

if let Maybe::Some(transfer_filter_contract_contract) = transfer_filter_contract_contract {
self.transfer_filter_contract
.set(transfer_filter_contract_contract);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure consistent error handling in the init function.

The function contains multiple conditions that lead to reversion using self.revert(...). However, there's an inconsistency in the handling of the is_minter_or_assigned condition (line 631). The function should revert if the condition is true, but it currently reverts if false. This is likely a logic error.

- if self.is_minter_or_assigned() {
+ if !self.is_minter_or_assigned() {
    self.revert(CEP78Error::InvalidOwnershipMode)
}

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.

Suggested change
pub fn init(
&mut self,
collection_name: String,
collection_symbol: String,
total_token_supply: u64,
ownership_mode: OwnershipMode,
nft_kind: NFTKind,
identifier_mode: NFTIdentifierMode,
nft_metadata_kind: NFTMetadataKind,
metadata_mutability: MetadataMutability,
receipt_name: String,
allow_minting: Maybe<bool>,
minting_mode: Maybe<MintingMode>,
holder_mode: Maybe<NFTHolderMode>,
whitelist_mode: Maybe<WhitelistMode>,
acl_white_list: Maybe<Vec<Address>>,
json_schema: Maybe<String>,
burn_mode: Maybe<BurnMode>,
operator_burn_mode: Maybe<bool>,
owner_reverse_lookup_mode: Maybe<OwnerReverseLookupMode>,
events_mode: Maybe<EventsMode>,
transfer_filter_contract_contract: Maybe<Address>,
additional_required_metadata: Maybe<Vec<NFTMetadataKind>>,
optional_metadata: Maybe<Vec<NFTMetadataKind>>
) {
let installer = self.caller();
let minting_mode = minting_mode.unwrap_or_default();
let owner_reverse_lookup_mode = owner_reverse_lookup_mode.unwrap_or_default();
let acl_white_list = acl_white_list.unwrap_or_default();
let whitelist_mode = whitelist_mode.unwrap_or_default();
let json_schema = json_schema.unwrap_or_default();
let is_whitelist_empty = acl_white_list.is_empty();
// Revert if minting mode is not ACL and acl list is not empty
if MintingMode::Acl != minting_mode && !is_whitelist_empty {
self.revert(CEP78Error::InvalidMintingMode)
}
// Revert if minting mode is ACL or holder_mode is contracts and acl list is locked and empty
if MintingMode::Acl == minting_mode
&& is_whitelist_empty
&& WhitelistMode::Locked == whitelist_mode
{
self.revert(CEP78Error::EmptyACLWhitelist)
}
// NOTE: It is commented out to allow having mutable metadata with hash identifier.
// NOTE: It's left for future reference.
// if identifier_mode == NFTIdentifierMode::Hash
// && metadata_mutability == MetadataMutability::Mutable
// {
// self.revert(CEP78Error::InvalidMetadataMutability)
// }
if ownership_mode == OwnershipMode::Minter
&& minting_mode == MintingMode::Installer
&& owner_reverse_lookup_mode == OwnerReverseLookupMode::Complete
{
self.revert(CEP78Error::InvalidReportingMode)
}
// Check if schema is missing before checking its validity
if nft_metadata_kind == NFTMetadataKind::CustomValidated && json_schema.is_empty() {
self.revert(CEP78Error::MissingJsonSchema)
}
// OwnerReverseLookup TransfersOnly mode should be Transferable
if OwnerReverseLookupMode::TransfersOnly == owner_reverse_lookup_mode
&& OwnershipMode::Transferable != ownership_mode
{
self.revert(CEP78Error::OwnerReverseLookupModeNotTransferable)
}
if ownership_mode != OwnershipMode::Transferable
&& transfer_filter_contract_contract.is_some()
{
self.revert(CEP78Error::TransferFilterContractNeedsTransferableMode)
}
self.data.init(
collection_name,
collection_symbol,
total_token_supply,
installer
);
self.settings.init(
allow_minting.unwrap_or(true),
minting_mode,
ownership_mode,
nft_kind,
holder_mode.unwrap_or_default(),
burn_mode.unwrap_or_default(),
events_mode.unwrap_or_default(),
operator_burn_mode.unwrap_or_default()
);
self.reverse_lookup
.init(owner_reverse_lookup_mode, receipt_name);
self.whitelist.init(acl_white_list.clone(), whitelist_mode);
self.metadata.init(
nft_metadata_kind,
additional_required_metadata,
optional_metadata,
metadata_mutability,
identifier_mode,
json_schema
);
if let Maybe::Some(transfer_filter_contract_contract) = transfer_filter_contract_contract {
self.transfer_filter_contract
.set(transfer_filter_contract_contract);
}
}
pub fn init(
&mut self,
collection_name: String,
collection_symbol: String,
total_token_supply: u64,
ownership_mode: OwnershipMode,
nft_kind: NFTKind,
identifier_mode: NFTIdentifierMode,
nft_metadata_kind: NFTMetadataKind,
metadata_mutability: MetadataMutability,
receipt_name: String,
allow_minting: Maybe<bool>,
minting_mode: Maybe<MintingMode>,
holder_mode: Maybe<NFTHolderMode>,
whitelist_mode: Maybe<WhitelistMode>,
acl_white_list: Maybe<Vec<Address>>,
json_schema: Maybe<String>,
burn_mode: Maybe<BurnMode>,
operator_burn_mode: Maybe<bool>,
owner_reverse_lookup_mode: Maybe<OwnerReverseLookupMode>,
events_mode: Maybe<EventsMode>,
transfer_filter_contract_contract: Maybe<Address>,
additional_required_metadata: Maybe<Vec<NFTMetadataKind>>,
optional_metadata: Maybe<Vec<NFTMetadataKind>>
) {
let installer = self.caller();
let minting_mode = minting_mode.unwrap_or_default();
let owner_reverse_lookup_mode = owner_reverse_lookup_mode.unwrap_or_default();
let acl_white_list = acl_white_list.unwrap_or_default();
let whitelist_mode = whitelist_mode.unwrap_or_default();
let json_schema = json_schema.unwrap_or_default();
let is_whitelist_empty = acl_white_list.is_empty();
// Revert if minting mode is not ACL and acl list is not empty
if MintingMode::Acl != minting_mode && !is_whitelist_empty {
self.revert(CEP78Error::InvalidMintingMode)
}
// Revert if minting mode is ACL or holder_mode is contracts and acl list is locked and empty
if MintingMode::Acl == minting_mode
&& is_whitelist_empty
&& WhitelistMode::Locked == whitelist_mode
{
self.revert(CEP78Error::EmptyACLWhitelist)
}
// NOTE: It is commented out to allow having mutable metadata with hash identifier.
// NOTE: It's left for future reference.
// if identifier_mode == NFTIdentifierMode::Hash
// && metadata_mutability == MetadataMutability::Mutable
// {
// self.revert(CEP78Error::InvalidMetadataMutability)
// }
if ownership_mode == OwnershipMode::Minter
&& minting_mode == MintingMode::Installer
&& owner_reverse_lookup_mode == OwnerReverseLookupMode::Complete
{
self.revert(CEP78Error::InvalidReportingMode)
}
// Check if schema is missing before checking its validity
if nft_metadata_kind == NFTMetadataKind::CustomValidated && json_schema.is_empty() {
self.revert(CEP78Error::MissingJsonSchema)
}
// OwnerReverseLookup TransfersOnly mode should be Transferable
if OwnerReverseLookupMode::TransfersOnly == owner_reverse_lookup_mode
&& OwnershipMode::Transferable != ownership_mode
{
self.revert(CEP78Error::OwnerReverseLookupModeNotTransferable)
}
if ownership_mode != OwnershipMode::Transferable
&& transfer_filter_contract_contract.is_some()
{
self.revert(CEP78Error::TransferFilterContractNeedsTransferableMode)
}
if !self.is_minter_or_assigned() {
self.revert(CEP78Error::InvalidOwnershipMode)
}
self.data.init(
collection_name,
collection_symbol,
total_token_supply,
installer
);
self.settings.init(
allow_minting.unwrap_or(true),
minting_mode,
ownership_mode,
nft_kind,
holder_mode.unwrap_or_default(),
burn_mode.unwrap_or_default(),
events_mode.unwrap_or_default(),
operator_burn_mode.unwrap_or_default()
);
self.reverse_lookup
.init(owner_reverse_lookup_mode, receipt_name);
self.whitelist.init(acl_white_list.clone(), whitelist_mode);
self.metadata.init(
nft_metadata_kind,
additional_required_metadata,
optional_metadata,
metadata_mutability,
identifier_mode,
json_schema
);
if let Maybe::Some(transfer_filter_contract_contract) = transfer_filter_contract_contract {
self.transfer_filter_contract
.set(transfer_filter_contract_contract);
}
}

Comment on lines +44 to +62
#[test]
fn should_disallow_minting_when_allow_minting_is_set_to_false() {
let env = odra_test::env();
let args = default_args_builder()
.nft_metadata_kind(NFTMetadataKind::NFT721)
.allow_minting(false)
.build();
let mut contract = Cep78HostRef::deploy(&env, args);

assert_eq!(
contract.try_mint(
env.get_account(0),
TEST_PRETTY_721_META_DATA.to_string(),
Maybe::None
),
Err(CEP78Error::MintingIsPaused.into()),
"should now allow minting when minting is disabled",
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure error message matches the function's intent.

- "should now allow minting when minting is disabled"
+ "should not allow minting when minting is disabled"

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.

Suggested change
#[test]
fn should_disallow_minting_when_allow_minting_is_set_to_false() {
let env = odra_test::env();
let args = default_args_builder()
.nft_metadata_kind(NFTMetadataKind::NFT721)
.allow_minting(false)
.build();
let mut contract = Cep78HostRef::deploy(&env, args);
assert_eq!(
contract.try_mint(
env.get_account(0),
TEST_PRETTY_721_META_DATA.to_string(),
Maybe::None
),
Err(CEP78Error::MintingIsPaused.into()),
"should now allow minting when minting is disabled",
);
}
#[test]
fn should_disallow_minting_when_allow_minting_is_set_to_false() {
let env = odra_test::env();
let args = default_args_builder()
.nft_metadata_kind(NFTMetadataKind::NFT721)
.allow_minting(false)
.build();
let mut contract = Cep78HostRef::deploy(&env, args);
assert_eq!(
contract.try_mint(
env.get_account(0),
TEST_PRETTY_721_META_DATA.to_string(),
Maybe::None
),
Err(CEP78Error::MintingIsPaused.into()),
"should not allow minting when minting is disabled",
);
}

Comment on lines +96 to +98
#[ignore = "Reverse lookup is not implemented yet"]
fn mint_should_return_dictionary_key_to_callers_owned_tokens() {
let env = odra_test::env();
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The search results indicate that while the reverse lookup feature is referenced and partially discussed in the codebase, there is no definitive evidence that it is fully implemented and operational. The comments in the code suggest that certain aspects of the feature, like data writing for owner lookup and page table allocation, are planned or partially implemented. However, the absence of a clear indication of a complete and functional implementation supports the decision to keep the related test ignored for now.

  • modules/src/cep78/token.rs: Mentions necessary steps to enable reverse lookup but requires explicit invocation, suggesting it's not fully integrated.
  • modules/src/cep78/modalities.rs: Discusses data handling for reverse lookup but also mentions an option where reverse lookup is not maintained, indicating conditional implementation.
Analysis chain

Clarify the status of the reverse lookup feature.

Please confirm whether the reverse lookup feature is implemented or if this test should remain ignored.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify if the reverse lookup feature is implemented.

# Test: Search for the implementation of reverse lookup. Expect: Implementation details or related comments.
rg --type rust 'reverse lookup'

Length of output: 575

let (mut contract, env) = default_token();
let owner = env.get_account(0);

// TODO: should register the owner first to create a page for the owner
Copy link
Contributor

Choose a reason for hiding this comment

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

Add necessary setup for the test to pass.

The comment indicates a missing setup step for registering the owner. Would you like me to help implement this setup step or open a GitHub issue to track this task?

Comment on lines +511 to +520
// TODO: Reverse lookup not implemented yet
/*
let token_page = get_token_page_by_hash(
&builder,
&nft_contract_key,
&Key::Account(*DEFAULT_ACCOUNT_ADDR),
token_id_hash,
);

assert!(token_page[0])*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Address the TODO regarding reverse lookup.

This TODO comment about reverse lookup not being implemented yet is linked to a large commented-out block of code. If you need assistance in implementing this feature or if it should be tracked via a GitHub issue, please let me know.

Comment on lines +117 to +162
fn approve_token_for_transfer_should_add_entry_to_approved_dictionary(
env: HostEnv,
operator: Option<Address>
) {
let args = default_args_builder()
.ownership_mode(OwnershipMode::Transferable)
.owner_reverse_lookup_mode(OwnerReverseLookupMode::Complete)
.events_mode(EventsMode::CES)
.build();
let mut contract = Cep78HostRef::deploy(&env, args);

let token_owner = env.get_account(0);
contract.register_owner(Maybe::Some(token_owner));
contract.mint(
token_owner,
TEST_PRETTY_721_META_DATA.to_string(),
Maybe::None
);

let spender = env.get_account(1);
let token_id = 0u64;

if let Some(operator) = operator {
assert!(contract.try_set_approval_for_all(true, operator).is_ok());
}

let approving_account = match operator {
Some(operator) => operator,
None => token_owner
};
env.set_caller(approving_account);
assert!(contract
.try_approve(spender, Maybe::Some(token_id), Maybe::None)
.is_ok());

let actual_approved_key = contract.get_approved(Maybe::Some(token_id), Maybe::None);
assert_eq!(actual_approved_key, Some(spender));

// Expect Approval event.
let expected_event = Approval::new(
token_owner,
spender,
TokenIdentifier::Index(token_id).to_string()
);
assert!(env.emitted_event(contract.address(), &expected_event));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Check for potential simplifications in approval tests.

// Simplify the approval setting by directly using the `operator` option in the `env.set_caller` method.
env.set_caller(operator.unwrap_or(token_owner));

Comment on lines +125 to +128
pub fn set_dictionary_value<T: CLTyped + ToBytes, U: AsRef<str>>(
&self,
dictionary_name: U,
key: V,
key: &[u8],
Copy link
Contributor

@coderabbitai coderabbitai bot May 7, 2024

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The examination of the set_dictionary_value function across different environments and modules in the codebase reveals varying approaches to error handling:

  1. WASM and VM Environments: These environments use the function normally, passing the parameters to underlying systems without explicit error handling in the function itself. Errors are likely handled at a lower level or expected to be managed by the calling function.

  2. Host Functions: Here, there is a check for the dictionary item key length, and an error is reverted if the key exceeds the maximum length. This shows explicit error handling within the function.

  3. Livenet Environment: This environment explicitly panics if the function is called, indicating that such operations are not supported in this environment under normal circumstances.

  4. Usage in Modules: In various modules, the function is used without additional error handling, suggesting reliance on the underlying implementations to manage errors.

Given these observations, the error handling for set_dictionary_value is not entirely consistent across the project. Different environments handle errors in distinct ways, ranging from no explicit handling to specific checks and panic conditions. This inconsistency might be intentional due to the differing nature of operations in each environment, but it could benefit from a review to ensure that error handling strategies are clear and appropriate for each context.

Recommendation: Review the error handling strategies used in different environments for set_dictionary_value to ensure they are appropriate and consider implementing more uniform error handling practices if feasible.

  • WASM and VM Environments: Confirm if error handling at lower levels is sufficient.
  • Host Functions: Maintain or adjust the explicit error checks as necessary.
  • Livenet Environment: Ensure that the panic conditions are well-documented and understood by users of the environment.
  • Module Usages: Consider adding error handling or documentation to clarify how errors should be managed.
Analysis chain

Ensure consistent error handling for set_dictionary_value.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify consistent error handling for `set_dictionary_value` across the project.

# Test: Search for the function usage. Expect: Consistent error handling.
rg --type rust $'set_dictionary_value'

Length of output: 1715



Script:

#!/bin/bash
# Description: Examine the implementations and usages of `set_dictionary_value` to verify error handling.

# Search for the function implementations and their surrounding code to check error handling mechanisms.
rg --type rust -C 10 "fn set_dictionary_value" 

# Search for usages of `set_dictionary_value` and check how errors are handled or propagated.
rg --type rust -C 10 "set_dictionary_value\("

Length of output: 27173

Copy link
Contributor

@kubaplas kubaplas May 10, 2024

Choose a reason for hiding this comment

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

DEEP RABBIT

Copy link
Contributor

Choose a reason for hiding this comment

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

@kubaplas, it seems like my previous message might have come as a surprise! If there's any part of the analysis you'd like to discuss further or if you have specific questions about the error handling strategies in different environments, feel free to let me know. I'm here to help!

Comment on lines +140 to +144
/// Removes the dictionary from the contract storage.
pub fn remove_dictionary<U: AsRef<str>>(&self, dictionary_name: U) {
let dictionary_name = dictionary_name.as_ref();
self.backend.borrow().remove_dictionary(dictionary_name);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The investigation into the remove_dictionary function across various modules reveals that while the function's conceptual role remains consistent (i.e., removing a dictionary from some form of storage), the implementation details vary. These variations are primarily in the parameters accepted (string references vs. byte arrays) and the internal handling within the function. Here are the key observations:

  • VM and Contract Environments: In odra-vm and odra-casper modules, the function primarily accepts string references. However, in the VM state management (odra-vm/src/vm/odra_vm_state.rs), a byte array is used, likely due to lower-level data handling requirements.
  • Host Functions and WASM Environment: The WASM environment uses host functions to bridge between WASM and the host environment, which consistently use string references.
  • Core and Module-Specific Implementations: The core implementation in core/src/contract_env.rs is flexible, allowing any type that can be referenced as a string, which is a higher-level abstraction compared to other implementations.

These differences seem justified based on the specific needs and contexts of each module. Therefore, while the implementations are not identical, they are consistent in purpose and adapted to their respective environments.

Analysis chain

Verify that remove_dictionary is implemented consistently across different modules.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify consistent implementation of `remove_dictionary` across different modules.

# Test: Search for the function usage. Expect: Consistent implementation.
rg --type rust $'remove_dictionary'

Length of output: 1254

modules/src/cep78/tests/burn.rs Show resolved Hide resolved
modules/src/cep78/tests/burn.rs Show resolved Hide resolved
Copy link

github-actions bot commented May 7, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.04788 CSPR (0.05%)
Contract Call Entry point: get_named_key 🟢 -0.00005448 CSPR (0.02%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

Copy link
Contributor

@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: 1

Out of diff range and nitpick comments (1)
examples/bin/cep78_on_livenet.rs (1)

28-34: Consider removing or clarifying the purpose of commented-out code.

The commented-out code for deploying a new contract and printing the token address (lines 28-30) could confuse maintainers or be accidentally uncommented. If this code is necessary for testing or future use, please add a comment explaining its purpose; otherwise, consider removing it.

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 7dda987 and a777639.
Files selected for processing (4)
  • examples/Cargo.toml (1 hunks)
  • examples/bin/cep78_on_livenet.rs (1 hunks)
  • modules/src/cep78/token.rs (1 hunks)
  • modules/src/cep78/utils.rs (1 hunks)
Files skipped from review due to trivial changes (1)
  • examples/Cargo.toml
Additional comments not posted (4)
examples/bin/cep78_on_livenet.rs (1)

76-78: Verify the necessity of the high gas setting for contract deployment.

The deploy_contract function sets a very high gas limit (line 76). While this might be necessary for contract deployment, it's important to ensure that this value is justified and optimized based on actual gas usage to avoid excessive costs.

modules/src/cep78/utils.rs (1)

159-332: Implementation of InitArgsBuilder follows best practices.

The InitArgsBuilder struct correctly implements the builder pattern, providing a flexible and clear way to construct initialization arguments for a CEP-78 contract. The use of the Maybe type for optional settings is a good practice.

modules/src/cep78/token.rs (2)

297-328: Implementation of the burn function is robust and well-structured.

The burn function in the Cep78 module correctly implements the logic for burning tokens, including comprehensive checks for ownership and burn status. The use of helper methods enhances readability and maintainability.


398-446: Implementation of approve and revoke functions meets standards.

The approve and revoke functions in the Cep78 module are correctly implemented with necessary checks for ownership and token burn status. The use of events to log approvals and revocations is a good practice.

Comment on lines 48 to 56
/// Loads a Cep78 contract.
fn _load_contract(env: &HostEnv) -> Cep78HostRef {
// casper-contract
// let address = "hash-d4b8fa492d55ac7a515c0c6043d72ba43c49cd120e7ba7eec8c0a330dedab3fb";
// odra-contract
let address = "hash-3d35238431c5c6fa1d7df70d73bfc2efd5a03fd5af99ab8c7828a56b2f330274";
let address = Address::from_str(address).unwrap();
Cep78HostRef::load(env, address)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Avoid using hardcoded addresses in production code.

The function _load_contract uses a hardcoded address (line 53), which is not ideal for production environments as it reduces flexibility and maintainability. Consider passing the address as a parameter or retrieving it from a configuration file or environment variable.

Copy link
Contributor

@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: 1

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between a777639 and f561155.
Files selected for processing (1)
  • modules/src/cep78/utils.rs (1 hunks)
Additional comments not posted (1)
modules/src/cep78/utils.rs (1)

306-331: The implementation of InitArgsBuilder follows the builder pattern correctly and is well-structured.

token_metadata: String,
is_reverse_lookup_enabled: bool
) -> (String, Address, String) {
let nft_contract_address = self.nft_contract.get().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Replace unwrap with safer error handling in MockContract.

- let nft_contract_address = self.nft_contract.get().unwrap();
+ let nft_contract_address = self.nft_contract.get().ok_or("NFT contract address not found")?;

This change should be applied to all instances where unwrap is used in this struct to prevent potential panics.


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.

Suggested change
let nft_contract_address = self.nft_contract.get().unwrap();
let nft_contract_address = self.nft_contract.get().ok_or("NFT contract address not found")?;

Copy link

github-actions bot commented May 7, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.04788 CSPR (0.05%)
Contract Call Entry point: get_named_key 🟢 -0.00005448 CSPR (0.02%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

Copy link
Contributor

@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: 1

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between f561155 and 9be2222.
Files selected for processing (1)
  • examples/bin/cep78_on_livenet.rs (1 hunks)
Additional comments not posted (2)
examples/bin/cep78_on_livenet.rs (2)

14-24: Avoid using hardcoded addresses in production code.

The function load_contract uses a hardcoded address (line 53), which is not ideal for production environments as it reduces flexibility and maintainability. Consider passing the address as a parameter or retrieving it from a configuration file or environment variable.


59-79: LGTM! The deployment function is well-structured and uses appropriate defaults for the contract.

Comment on lines +26 to +50
fn main() {
let env = odra_casper_livenet_env::env();

// Deploy new contract.
let mut token = deploy_contract(&env);
println!("Token address: {}", token.address().to_string());

// Uncomment to load existing contract.
// let mut token = load_contract(&env, CASPER_CONTRACT_ADDRESS);
// println!("Token name: {}", token.get_collection_name());

env.set_gas(3_000_000_000u64);
let owner = env.caller();
let recipient =
Address::from_str(RECIPIENT_ADDRESS).expect("Should be a valid recipient address");
// casper contract may return a result or not, so deserialization may fail and it's better to use `try_transfer`/`try_mint`/`try_burn` methods
let _ = token.try_mint(owner, CEP78_METADATA.to_string(), Maybe::None);
println!("Owner's balance: {:?}", token.balance_of(owner));
println!("Recipient's balance: {:?}", token.balance_of(recipient));
let token_id = token.get_number_of_minted_tokens() - 1;
let _ = token.try_transfer(Maybe::Some(token_id), Maybe::None, owner, recipient);

println!("Owner's balance: {:?}", token.balance_of(owner));
println!("Recipient's balance: {:?}", token.balance_of(recipient));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Improve error handling and avoid hardcoded values.

Consider enhancing the error handling around try_mint and try_transfer methods to ensure that failures are handled gracefully. Additionally, avoid using hardcoded values such as gas amounts and instead retrieve them from a configuration or environment variable to increase flexibility.

Copy link

github-actions bot commented May 8, 2024

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.04032 CSPR (0.04%)
Contract Call Entry point: get_named_key 🟢 -0.00005448 CSPR (0.02%)
Contract Call Entry point: get_dictionary 🔴 +0.00042516 CSPR (0.09%)

Copy link
Contributor

@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: 0

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 9be2222 and f653b6e.
Files selected for processing (1)
  • justfile (1 hunks)
Files skipped from review due to trivial changes (1)
  • justfile

Copy link
Contributor

@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: 0

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between f653b6e and 08e3f49.
Files selected for processing (1)
  • modules/src/cep78/events.rs (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • modules/src/cep78/events.rs

Copy link

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🔴 +0.096112482 CSPR (0.06%)
Contract Call Entry point: get_named_key 🟢 -0.00005448 CSPR (0.01%)
Contract Call Entry point: get_dictionary 🔴 +0.00002016 CSPR (0.01%)

@zie1ony zie1ony merged commit 00c2d4f into release/1.0.0 May 10, 2024
4 checks passed
@zie1ony zie1ony deleted the feature/cep-78 branch May 10, 2024 12:59
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.

3 participants