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

Nft Staking #11

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

Nft Staking #11

wants to merge 12 commits into from

Conversation

oneShot0430
Copy link

@oneShot0430 oneShot0430 commented Jul 16, 2024

Contact Information

Summary: With the Nft Staking ADO, nft holders can stake their nft to gain rewards. With enough incentive for asset holders, it will play an important role to keep the market active and attract more people to create and hold nfts.

This is the solution of #8

Messages:

Instantiate

pub struct InstantiateMsg {
    pub denom: String,
    pub rewards_per_token: Vec<(String, u128)>,
    pub unbonding_period: Option<u64>,
    pub payout_window: Option<u64>,
}  

The ADO creator instantiates the contract with reward denomiation, a list of rewards amount for nft contract address, unbonding period for nfts and the payout window which defines the frequency of the reward distribution.

ExecuteMsg

pub enum ExecuteMsg {
    ReceiveNft(Cw721ReceiveMsg),
    ClaimReward {
        nft_address: String,
        token_id: String,
    },
    ClaimAsset {
        nft_address: String,
        token_id: String,
    },
    Unstake {
        nft_address: String,
        token_id: String,
    },
    UpdateConfig {
        unbonding_period: u64,
    },
}
  • The nft holder can stake their token by sending nft using SendNft to the Nft Staking ADO.
  • Stakers claim rewards using ClaimReward message with the token address and id they staked.
  • Stakers can unstake staked tokens using Unstake with the token address and token id they staked. Once token is unstaked, no rewards will be distributed for that token and user can claim the asset after unbonding period
  • Stakers can claim unstaked asset after unbonding period using ClaimAsset message. The token will be transferred back to the user
  • Owner of the Nft Staking ADO can update the unbonding period using UpdateConfig message. The applied unbonding period will be applied for future unstaking activity.

QueryMsg

pub enum QueryMsg {
    #[returns(ConfigResponse)]
    Config {},
    #[returns(RewardsPerTokenResponse)]
    RewardsPerToken {},
    #[returns(StakersResponse)]
    Stakers {},
    #[returns(StakerDetailResponse)]
    StakerDetail { staker: String },
    #[returns(AssetDetailResponse)]
    AssetDetail {
        nft_address: String,
        token_id: String,
    },
}
  • Config
    Returns configuration for the Nft Staking ADO as ConfigResponse.
pub struct ConfigResponse {
    pub denom: String,
    pub unbonding_period: Milliseconds,
    pub payout_window: Milliseconds,
}
  • RewardsPerToken
    Returns the list of pairs of token price and reward as RewardsPerTokenResponse.
pub struct RewardsPerTokenResponse {
    pub rewards_per_token: Vec<(String, u128)>,
}
  • Stakers
    Returns the list of stakers in StakersResponse
pub struct StakersResponse {
    pub stakers: Vec<String>,
}
  • StakerDetail
    Returns the list of staked assets and total pending reward for the staker.
pub struct StakerDetailResponse {
    pub assets: Vec<(String, String)>,
    pub pending_rewards: u128,
}

assets is specifying the list of (token_address, token_id)

  • AssetDetail
    Returns the staked asset's detailed information.
pub struct AssetDetailResponse {
    pub asset_detail: AssetDetail,
}

Notes

  • Currently, Nft Staking ADO is not supporting amp messages due to execute_amp_receive function's return value . That is reported via this
  • For the project template, it was using call_action before handling ExecuteMsg. However, it was not suitable to call_action for non andromeda-core projects. (When writing an integration test for the SendNft, call_action was returning InvalidAddress error for valid addresses), As call_action is for andromeda-core ADO architecture, like app component -> modules, it was not suitable for custom ADO development

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced NFT staking functionality, enabling users to stake, unstake, and claim rewards associated with NFTs.
    • Added support for receiving NFTs and updating contract configurations.
  • Documentation

    • Added comprehensive README for setting up and developing NFT staking contracts.
    • Introduced LICENSE and NOTICE files for legal and licensing information.
  • Tests

    • Introduced integration tests to validate functionalities related to staking, rewards claiming, unstaking, and asset claiming.

Copy link

coderabbitai bot commented Jul 16, 2024

Walkthrough

The updates introduce a robust NFT staking module for smart contracts, enabling functionalities like staking, unstaking, and claiming rewards. This new module enhances state management and error handling while providing a user-friendly experience for NFT holders. Additionally, integration tests ensure comprehensive validation of all features, promoting reliability and security in the contract's operations.

Changes

File(s) Change Summary
ADOs/nft-staking/src/execute.rs, ADOs/nft-staking/src/msg.rs, ADOs/nft-staking/src/state.rs Implemented NFT staking logic, defined message structures, and established data management for configuration, stakers, and rewards.
ADOs/nft-staking/tests/integration_tests.rs Added comprehensive integration tests to ensure the NFT staking module functions as intended across various scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Contract
    participant State

    User ->> Contract: Receive NFT
    Contract ->> State: Update Staker Details
    State ->> Contract: Confirm Receipt

    User ->> Contract: Claim Reward
    Contract ->> State: Calculate Rewards
    State ->> Contract: Return Rewards
    Contract ->> User: Transfer Rewards

    User ->> Contract: Unstake NFT
    Contract ->> State: Update Unbonding Status
    State ->> Contract: Confirm Unstake

    User ->> Contract: Claim Unstaked NFT
    Contract ->> State: Check Unbonding Period
    State ->> Contract: Confirm Claim
    Contract ->> User: Transfer NFT
Loading

Poem

In a world of tokens, we hop and play,
Staking our dreams in a bright ballet.
With contracts and rewards, we dance and sing,
A blockchain journey, oh what joy it brings!
Through every test, our hopes take flight,
Together we thrive, in code's pure light!
🐇✨🌼


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.
    • @coderabbitai help me debug CodeRabbit configuration file.

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 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

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.

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: 10

Outside diff range, codebase verification and nitpick comments (3)
ADOs/nft-staking/src/helpers.rs (1)

1-27: Helper Functions Approved with Suggestion for Improvement

The helper functions in helpers.rs are well-designed and facilitate contract interaction effectively. However, adding documentation comments for the public functions would improve maintainability and clarity for other developers.

+/// Returns the address of the contract.
  pub fn addr(&self) -> Addr {
ADOs/nft-staking/src/state.rs (1)

68-77: Check error handling in get_asset_detail.

The calculate_pending_rewards function does not handle errors gracefully. It uses unwrap_or_default and unwrap, which can cause the program to panic if any operation fails. This needs to be addressed to ensure robust error handling.

  • Modify the calculate_pending_rewards function to handle errors properly instead of using unwrap_or_default and unwrap.
Analysis chain

Check error handling in get_asset_detail.

This function modifies the pending_rewards field based on a calculation, which is a critical operation. Ensure that calculate_pending_rewards handles errors internally since its result directly affects the state.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify error handling in the calculate_pending_rewards function.
rg --type rust -A 5 "fn calculate_pending_rewards"

Length of output: 434


Script:

#!/bin/bash
# Description: Retrieve the full implementation of the calculate_pending_rewards function to check for error handling.
rg --type rust -A 50 "fn calculate_pending_rewards" ADOs/nft-staking/src/state.rs

Length of output: 976

ADOs/nft-staking/src/contract.rs (1)

67-107: Execution function handles different messages appropriately.

The execute function routes different message types to their respective handlers effectively. The pattern matching in Rust is used correctly to handle different types of ExecuteMsg.

Consider removing commented code if it's not intended for future use to keep the codebase clean and maintainable.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 63d9a0c and c3dad06.

Files ignored due to path filters (1)
  • ADOs/nft-staking/Cargo.lock is excluded by !**/*.lock
Files selected for processing (21)
  • ADOs/nft-staking/.cargo/config (1 hunks)
  • ADOs/nft-staking/.circleci/config.yml (1 hunks)
  • ADOs/nft-staking/.editorconfig (1 hunks)
  • ADOs/nft-staking/.github/workflows/Basic.yml (1 hunks)
  • ADOs/nft-staking/.github/workflows/Release.yml (1 hunks)
  • ADOs/nft-staking/.gitignore (1 hunks)
  • ADOs/nft-staking/Cargo.toml (1 hunks)
  • ADOs/nft-staking/LICENSE (1 hunks)
  • ADOs/nft-staking/NOTICE (1 hunks)
  • ADOs/nft-staking/README.md (1 hunks)
  • ADOs/nft-staking/src/bin/schema.rs (1 hunks)
  • ADOs/nft-staking/src/config.rs (1 hunks)
  • ADOs/nft-staking/src/contract.rs (1 hunks)
  • ADOs/nft-staking/src/error.rs (1 hunks)
  • ADOs/nft-staking/src/execute.rs (1 hunks)
  • ADOs/nft-staking/src/helpers.rs (1 hunks)
  • ADOs/nft-staking/src/integration_tests.rs (1 hunks)
  • ADOs/nft-staking/src/lib.rs (1 hunks)
  • ADOs/nft-staking/src/msg.rs (1 hunks)
  • ADOs/nft-staking/src/query.rs (1 hunks)
  • ADOs/nft-staking/src/state.rs (1 hunks)
Files skipped from review due to trivial changes (5)
  • ADOs/nft-staking/.cargo/config
  • ADOs/nft-staking/.gitignore
  • ADOs/nft-staking/LICENSE
  • ADOs/nft-staking/NOTICE
  • ADOs/nft-staking/src/config.rs
Additional context used
LanguageTool
ADOs/nft-staking/README.md

[uncategorized] ~7-~7: Possible missing comma found.
Context: ...on To see what's involved in making an ADO check out our documentation [here](http...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~18-~18: You might be missing the article “a” here.
Context: ...et coding. ## Creating a new repo from template Assuming you have a recent version of ...

(AI_EN_LECTOR_MISSING_DETERMINER_A)


[misspelling] ~52-~52: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’.
Context: ...eate a Repo After generating, you have a initialized local git repo, but no comm...

(EN_A_VS_AN)


[uncategorized] ~53-~53: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...commits, and no remote. Go to a server (eg. github) and create a new upstream repo ...

(E_G)


[style] ~73-~73: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...s with --locked to ensure it uses the exact same versions as you have locally. This also...

(EN_WORDINESS_PREMIUM_EXACT_SAME)

Markdownlint
ADOs/nft-staking/README.md

35-35: null
Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

Additional comments not posted (33)
ADOs/nft-staking/.editorconfig (1)

1-11: Editor Configuration Approved

The .editorconfig file is well-configured to ensure consistent coding styles across the project, particularly with the Rust-specific indentation setting which aligns with common Rust conventions.

ADOs/nft-staking/src/lib.rs (1)

1-12: Module Organization Approved

The organization of modules in lib.rs is clear and modular, which will facilitate maintenance and scalability. The re-export of ContractError is a good practice for centralized error management.

ADOs/nft-staking/src/bin/schema.rs (1)

1-11: Schema Generation Logic Approved

The schema generation setup in schema.rs is correctly implemented using cosmwasm_schema::write_api. This setup is crucial for contract interaction and is well configured.

ADOs/nft-staking/.github/workflows/Release.yml (2)

3-5: Confirm the trigger event for the workflow.

The workflow is triggered on the creation of a release. Ensure this aligns with the project's release strategy.

Verification successful

The trigger event for the workflow is correctly configured.

The workflow is appropriately triggered by the creation of a release, and there are no other workflows in the repository that conflict with this trigger.

  • No conflicting or redundant workflows found.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if the release trigger aligns with other workflows in the repository.

# Test: Search for other workflows that might be triggered on release to ensure there are no conflicts or redundancies.
rg --type yaml 'on:\s+release' -g '*.yml'

Length of output: 192


Script:

#!/bin/bash
# Description: Verify if the release trigger aligns with other workflows in the repository.

# Test: Search for other workflows that might be triggered on release to ensure there are no conflicts or redundancies.
rg --type yaml 'on:\s+release' -g '*.yml' --debug

Length of output: 6571


Script:

#!/bin/bash
# Description: Verify if the release trigger aligns with other workflows in the repository.

# Test: Search for other workflows that might be triggered on release to ensure there are no conflicts or redundancies.
rg --type yaml 'on:\s+release' -g '*.yml' --hidden

Length of output: 52


11-35: Review the workflow steps for correctness and security.

The steps include checking out the repository, installing a cargo run script, optimizing the wasm binary, and uploading it to a release. The usage of actions/checkout@v2 and actions-rs/cargo@v1 is standard and appropriate. However, ensure that the GITHUB_TOKEN and secrets.GITHUB_TOKEN are properly managed and that the permissions are correctly configured.

Verification successful

Workflow steps are correct and secure.

The usage of GITHUB_TOKEN and secrets.GITHUB_TOKEN in the workflow file is standard and appropriate. The actions used (actions/checkout@v2, actions-rs/cargo@v1, bruceadams/[email protected], and svenstaro/upload-release-action@v2) are well-known and reliable.

  • Lines 27 and 31: Proper usage of GITHUB_TOKEN and secrets.GITHUB_TOKEN.
  • Actions used are standard and secure.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the GitHub token permissions in the repository settings.

# Test: This script is conceptual as token permissions can only be verified manually through the GitHub UI.
echo "Please manually verify the GITHUB_TOKEN permissions in the repository settings."

Length of output: 168


Script:

#!/bin/bash
# Description: Verify the usage of GITHUB_TOKEN and secrets.GITHUB_TOKEN in the workflow file for potential security issues.

# Search for the usage of GITHUB_TOKEN in the workflow file
echo "Checking for GITHUB_TOKEN usage in the workflow file..."
grep -n 'GITHUB_TOKEN' ADOs/nft-staking/.github/workflows/Release.yml

# Search for the usage of secrets.GITHUB_TOKEN in the workflow file
echo "Checking for secrets.GITHUB_TOKEN usage in the workflow file..."
grep -n 'secrets.GITHUB_TOKEN' ADOs/nft-staking/.github/workflows/Release.yml

# List all actions used in the workflow file to check for any potential security issues
echo "Listing all actions used in the workflow file..."
grep -n 'uses:' ADOs/nft-staking/.github/workflows/Release.yml

Length of output: 938

ADOs/nft-staking/Cargo.toml (1)

1-50: Review the package configuration and dependencies.

The package configuration is correctly set with appropriate authors and versioning. Dependencies like cosmwasm-std and cw721 are correctly specified for a blockchain contract. The build settings are optimized for release, which is suitable for a production environment.

ADOs/nft-staking/.circleci/config.yml (1)

3-61: Review the CircleCI configuration for Docker operations.

The configuration uses Docker layer caching and conditional logic for pushing images, which is efficient. However, ensure that the Docker credentials (DOCKER_USER and DOCKER_PASS) are securely stored in CircleCI's environment variables and not hardcoded.

ADOs/nft-staking/.github/workflows/Basic.yml (4)

1-1: General Comment: Good reference usage.

The comment indicates that this workflow is based on a well-known example, which is a good practice for maintainability and understanding.


3-3: General Comment: Trigger events specified.

The workflow is triggered on push and pull_request events, which is typical and ensures that the code is tested and linted frequently.


7-39: General Comment: Test job configuration.

The test job is well structured with steps for checking out code, setting up the Rust environment, running unit tests, and compiling the WASM contract. Each step uses appropriate actions and specifies necessary configurations such as toolchain version and environment variables.


40-75: General Comment: Lint and schema generation job.

This job handles linting and schema generation. It is correctly set up with steps for checking out code, installing toolchain components, running cargo fmt and clippy, and ensuring no schema changes are uncommitted. This ensures code quality and consistency.

ADOs/nft-staking/src/query.rs (4)

12-18: General Comment: Configuration query implementation.

The function query_config correctly retrieves configuration settings from the contract's state. The use of CONFIG.load with proper error handling is commendable.


21-23: General Comment: Rewards query implementation.

The function query_rewards_per_token is implemented correctly, fetching rewards data efficiently and handling errors appropriately.


26-31: General Comment: Stakers query implementation.

The function query_stakers efficiently lists all stakers. The use of .keys with Order::Ascending is appropriate for this context.


62-70: General Comment: Asset detail query implementation.

This function correctly fetches detailed information about a specific asset. The error handling and structure of the response are appropriate.

ADOs/nft-staking/src/msg.rs (4)

17-28: General Comment: Instantiate message structure.

The InstantiateMsg struct is well-defined with clear documentation and appropriate data types. The inclusion of optional fields for unbonding period and payout window allows flexibility in contract configuration.


30-49: General Comment: Execution message enumeration.

The ExecuteMsg enum covers all necessary operations for the NFT staking functionality, such as receiving NFTs, claiming rewards, and updating configuration. The structure is clear and well-documented.


51-68: General Comment: Query message enumeration.

The QueryMsg enum is comprehensive, covering all necessary queries for the contract. The use of custom response types for each query ensures type safety and clarity.


70-104: General Comment: Validation logic in InstantiateMsg.

The validation logic is robust, ensuring no duplicated assets, non-zero rewards, and adherence to minimum requirements for unbonding periods and payout windows. This prevents common configuration errors and enforces contract integrity.

ADOs/nft-staking/README.md (2)

1-3: General Comment: Introduction and reference to template.

The introduction clearly states the purpose of the repository and references the original template, which is helpful for users to understand the context.


5-17: General Comment: Documentation and template usage instructions.

The documentation links and instructions on using the template are clear and concise, providing users with necessary resources to get started.

Tools
LanguageTool

[uncategorized] ~7-~7: Possible missing comma found.
Context: ...on To see what's involved in making an ADO check out our documentation [here](http...

(AI_HYDRA_LEO_MISSING_COMMA)

ADOs/nft-staking/src/state.rs (4)

8-14: Config struct definition looks good.

The Config struct is well-defined and appropriately uses Rust's Default trait to provide default values. The use of the cw_serde attribute ensures compatibility with CosmWasm's serialization requirements.


16-21: StakerDetail struct definition is appropriate.

The StakerDetail struct is simple and efficiently stores a list of assets. It is correctly marked for serialization and uses the Default trait, which is suitable for initializing new staker entries.


23-32: AssetDetail struct definition is comprehensive.

The AssetDetail struct includes all necessary fields to track the staking details of an asset, including rewards and timestamps. The optional unstaked_at field is a good design choice, allowing for flexibility in handling the staking lifecycle.


63-66: Proper error handling in get_staker_detail.

The function correctly handles potential errors by propagating them using ?, which is a good practice in Rust for error handling.

ADOs/nft-staking/src/integration_tests.rs (2)

1-8: Use of appropriate testing framework and setup.

The use of #![cfg(test)] ensures that this code is only compiled in test mode, which is good for separating test code from production code. The imports and setup using cosmwasm_std and cw_multi_test are appropriate for the intended testing of a CosmWasm contract.


10-44: Correct setup of contract wrappers and address generation.

The functions contract_nft_staking and contract_cw721 correctly wrap the contract logic for instantiation, execution, and querying. The use of MockApiBech32 for address generation in generate_mock_address is a standard approach in testing environments.

ADOs/nft-staking/src/contract.rs (2)

109-129: Query handlers are implemented correctly.

The query function correctly handles different query messages and encodes the responses properly. The use of encode_binary ensures that the responses are correctly formatted for the CosmWasm environment.


131-261: Comprehensive unit tests for contract instantiation.

The tests cover various scenarios including valid instantiation, error handling for invalid asset denominations, and checks for empty or duplicated rewards. These tests are crucial for ensuring the contract behaves as expected under different conditions.

ADOs/nft-staking/src/execute.rs (4)

70-104: Claim rewards function correctly calculates and distributes rewards.

The claim_reward function efficiently processes pending rewards and sends the correct amount to the staker. The separation of concerns and clear logic flow in this function are commendable.


106-149: Unstake function correctly handles asset unstaking with proper checks.

The unstake function includes necessary checks such as whether the asset is already unstaked and if the caller is authorized. This prevents unauthorized access and double unstaking, which are critical for contract security.


151-223: Claim asset function ensures all conditions are met before asset transfer.

The claim_asset function correctly checks that the asset has passed the unbonding period and that the caller is authorized before allowing the asset claim. This prevents premature claims and ensures that only rightful owners can claim assets.


225-260: Config update function includes necessary validations and updates.

The update_config function properly checks for authorization and validates the new unbonding period before updating the configuration. This prevents unauthorized configuration changes and ensures that updates meet the required conditions.

ADOs/nft-staking/src/state.rs Outdated Show resolved Hide resolved
ADOs/nft-staking/src/state.rs Outdated Show resolved Hide resolved
ADOs/nft-staking/src/query.rs Show resolved Hide resolved
ADOs/nft-staking/README.md Show resolved Hide resolved
ADOs/nft-staking/src/error.rs Show resolved Hide resolved
ADOs/nft-staking/src/error.rs Show resolved Hide resolved
ADOs/nft-staking/src/integration_tests.rs Show resolved Hide resolved
ADOs/nft-staking/src/contract.rs Show resolved Hide resolved
ADOs/nft-staking/src/execute.rs Outdated Show resolved Hide resolved
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: 4

Outside diff range, codebase verification and nitpick comments (5)
ADOs/nft-staking/src/execute.rs (5)

18-68: Consider adding detailed logging in receive_cw721.

Adding more detailed logging for each step can aid in debugging and monitoring contract interactions.

+        .add_attribute("action", "validate_nft")
+        .add_attribute("action", "update_staker_details")
+        .add_attribute("action", "update_asset_details")

70-104: Consider adding detailed logging in claim_reward.

Adding more detailed logging for each step can aid in debugging and monitoring contract interactions.

+        .add_attribute("action", "validate_staker")
+        .add_attribute("action", "process_rewards")

106-149: Consider adding detailed logging in unstake.

Adding more detailed logging for each step can aid in debugging and monitoring contract interactions.

+        .add_attribute("action", "validate_staker")
+        .add_attribute("action", "update_asset_details")

151-223: Consider adding detailed logging in claim_asset.

Adding more detailed logging for each step can aid in debugging and monitoring contract interactions.

+        .add_attribute("action", "validate_unstaking_period")
+        .add_attribute("action", "update_staker_details")
+        .add_attribute("action", "transfer_nft")

225-801: Consider adding detailed logging in update_config.

Adding more detailed logging for each step can aid in debugging and monitoring contract interactions.

+        .add_attribute("action", "validate_owner")
+        .add_attribute("action", "update_config")
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between c3dad06 and 02377c9.

Files selected for processing (3)
  • ADOs/nft-staking/src/execute.rs (1 hunks)
  • ADOs/nft-staking/src/msg.rs (1 hunks)
  • ADOs/nft-staking/src/state.rs (1 hunks)
Additional comments not posted (12)
ADOs/nft-staking/src/msg.rs (6)

1-15: LGTM! Imports are necessary and relevant.

The imports are appropriate and necessary for the functionality provided in the file.


17-28: LGTM! InstantiateMsg struct is well-defined.

The struct includes necessary fields with appropriate comments and allows for flexibility using Option.


30-49: LGTM! ExecuteMsg enum covers all necessary execution messages.

The enum is comprehensive and includes all required messages for the contract functionality.


51-68: LGTM! QueryMsg enum covers all necessary query messages.

The enum is comprehensive and includes all required messages for querying contract state.


70-104: LGTM! InstantiateMsg validation logic is thorough.

The validation logic includes necessary checks for duplicate assets, zero rewards, empty rewards, and minimum periods.


107-130: LGTM! Response structs are well-defined.

The response structs include necessary fields for configuration, rewards, stakers, and asset details.

ADOs/nft-staking/src/state.rs (5)

1-7: LGTM! Imports are necessary and relevant.

The imports are appropriate and necessary for the functionality provided in the file.


8-32: LGTM! State structs are well-defined.

The structs include necessary fields with appropriate comments and use the Default trait for initializing default values.


34-40: LGTM! State constants are well-defined.

The constants use appropriate storage utilities from cw_storage_plus.


68-77: Ensure proper error handling in get_asset_detail.

The function uses .unwrap() which could panic if there's an error during storage operations. It's safer to handle these potential errors gracefully to avoid panicking the contract.

-    let mut asset_detail = ASSET_DETAILS.load(store, (nft_address, token_id))?;
+    let mut asset_detail = ASSET_DETAILS.load(store, (nft_address, token_id)).map_err(|_| ContractError::StorageError)?;

Likely invalid or redundant comment.


63-66: Ensure proper error handling in get_staker_detail.

The function uses .unwrap() which could panic if there's an error during storage operations. It's safer to handle these potential errors gracefully to avoid panicking the contract.

-    let staker_detail = STAKER_DETAILS.load(store, &staker)?;
+    let staker_detail = STAKER_DETAILS.load(store, &staker).map_err(|_| ContractError::StorageError)?;

Likely invalid or redundant comment.

ADOs/nft-staking/src/execute.rs (1)

1-16: LGTM! Imports are necessary and relevant.

The imports are appropriate and necessary for the functionality provided in the file.

Comment on lines 103 to 131
pub fn calculate_pending_rewards(
store: &dyn Storage,
block: &BlockInfo,
asset_detail: AssetDetails,
) -> Uint128 {
// For nfts in unbonding period, just return original pending rewards
if asset_detail.unstaked_at.is_some() {
return asset_detail.pending_rewards;
}

let unpaid_duration: u128 = block
.time
.nanos()
.checked_sub(asset_detail.updated_at.nanos())
.unwrap_or_default() as u128;
let config = CONFIG.load(store).unwrap_or_default();

let window_count = Uint128::new(unpaid_duration.checked_div(config.payout_window.nanos() as u128).unwrap());

let reward_per_window = REWARDS_PER_TOKEN
.load(store, &asset_detail.nft_address)
.unwrap_or_default();

window_count
.checked_mul(reward_per_window)
.unwrap_or_default()
.checked_add(asset_detail.pending_rewards)
.unwrap()
}
Copy link

Choose a reason for hiding this comment

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

Ensure proper error handling in calculate_pending_rewards.

The function uses .unwrap() which could panic if there's an error during storage operations. It's safer to handle these potential errors gracefully to avoid panicking the contract.

-    let config = CONFIG.load(store).unwrap_or_default();
+    let config = CONFIG.load(store).map_err(|_| ContractError::StorageError)?;

Committable suggestion was skipped due to low confidence.

Comment on lines 79 to 101
pub fn process_pending_rewards(
store: &mut dyn Storage,
block: &BlockInfo,
nft_address: String,
token_id: String,
) -> Result<Uint128, ContractError> {
let mut asset_detail = ASSET_DETAILS.load(store, (nft_address.clone(), token_id.clone()))?;
let pending_rewards = calculate_pending_rewards(store, block, asset_detail.clone());
ensure!(!pending_rewards.is_zero(), ContractError::ZeroReward {});

let unpaid_duration = block
.time
.nanos()
.checked_sub(asset_detail.updated_at.nanos())
.unwrap_or_default();

let config = CONFIG.load(store).unwrap_or_default();
let remainder = unpaid_duration % config.payout_window.nanos();
asset_detail.pending_rewards = Uint128::zero();
asset_detail.updated_at = Milliseconds::from_nanos(block.time.nanos().checked_sub(remainder).unwrap());
ASSET_DETAILS.save(store, (nft_address, token_id), &asset_detail)?;
Ok(pending_rewards)
}
Copy link

Choose a reason for hiding this comment

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

Ensure proper error handling in process_pending_rewards.

The function uses .unwrap() which could panic if there's an error during storage operations. It's safer to handle these potential errors gracefully to avoid panicking the contract.

-    let config = CONFIG.load(store).unwrap_or_default();
+    let config = CONFIG.load(store).map_err(|_| ContractError::StorageError)?;
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
pub fn process_pending_rewards(
store: &mut dyn Storage,
block: &BlockInfo,
nft_address: String,
token_id: String,
) -> Result<Uint128, ContractError> {
let mut asset_detail = ASSET_DETAILS.load(store, (nft_address.clone(), token_id.clone()))?;
let pending_rewards = calculate_pending_rewards(store, block, asset_detail.clone());
ensure!(!pending_rewards.is_zero(), ContractError::ZeroReward {});
let unpaid_duration = block
.time
.nanos()
.checked_sub(asset_detail.updated_at.nanos())
.unwrap_or_default();
let config = CONFIG.load(store).unwrap_or_default();
let remainder = unpaid_duration % config.payout_window.nanos();
asset_detail.pending_rewards = Uint128::zero();
asset_detail.updated_at = Milliseconds::from_nanos(block.time.nanos().checked_sub(remainder).unwrap());
ASSET_DETAILS.save(store, (nft_address, token_id), &asset_detail)?;
Ok(pending_rewards)
}
pub fn process_pending_rewards(
store: &mut dyn Storage,
block: &BlockInfo,
nft_address: String,
token_id: String,
) -> Result<Uint128, ContractError> {
let mut asset_detail = ASSET_DETAILS.load(store, (nft_address.clone(), token_id.clone()))?;
let pending_rewards = calculate_pending_rewards(store, block, asset_detail.clone());
ensure!(!pending_rewards.is_zero(), ContractError::ZeroReward {});
let unpaid_duration = block
.time
.nanos()
.checked_sub(asset_detail.updated_at.nanos())
.unwrap_or_default();
let config = CONFIG.load(store).map_err(|_| ContractError::StorageError)?;
let remainder = unpaid_duration % config.payout_window.nanos();
asset_detail.pending_rewards = Uint128::zero();
asset_detail.updated_at = Milliseconds::from_nanos(block.time.nanos().checked_sub(remainder).unwrap());
ASSET_DETAILS.save(store, (nft_address, token_id), &asset_detail)?;
Ok(pending_rewards)
}

Comment on lines +53 to +61
pub fn get_rewards_per_token(store: &dyn Storage) -> Result<Vec<(String, u128)>, ContractError> {
Ok(REWARDS_PER_TOKEN
.range_raw(store, None, None, cosmwasm_std::Order::Ascending)
.map(|item| {
let item = item.unwrap();
(String::from_utf8(item.0).unwrap(), item.1.u128())
})
.collect())
}
Copy link

Choose a reason for hiding this comment

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

Ensure proper error handling in get_rewards_per_token.

The function uses .unwrap() which could panic if there's an error during decoding. It's safer to handle these potential errors gracefully to avoid panicking the contract.

-            let item = item.unwrap();
+            let item = item.map_err(|_| ContractError::StorageError)?;
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
pub fn get_rewards_per_token(store: &dyn Storage) -> Result<Vec<(String, u128)>, ContractError> {
Ok(REWARDS_PER_TOKEN
.range_raw(store, None, None, cosmwasm_std::Order::Ascending)
.map(|item| {
let item = item.unwrap();
(String::from_utf8(item.0).unwrap(), item.1.u128())
})
.collect())
}
pub fn get_rewards_per_token(store: &dyn Storage) -> Result<Vec<(String, u128)>, ContractError> {
Ok(REWARDS_PER_TOKEN
.range_raw(store, None, None, cosmwasm_std::Order::Ascending)
.map(|item| {
let item = item.map_err(|_| ContractError::StorageError)?;
(String::from_utf8(item.0).unwrap(), item.1.u128())
})
.collect())
}

Comment on lines +42 to +52
pub fn set_rewards_per_token(
store: &mut dyn Storage,
rewards_per_token: Vec<(String, u128)>,
) -> Result<(), ContractError> {
rewards_per_token.iter().for_each(|item| {
REWARDS_PER_TOKEN
.save(store, &item.0, &Uint128::from(item.1))
.unwrap();
});
Ok(())
}
Copy link

Choose a reason for hiding this comment

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

Ensure proper error handling in set_rewards_per_token.

The function uses .unwrap() which could panic if there's an error during storage operations. It's safer to handle these potential errors gracefully to avoid panicking the contract.

-            .unwrap();
+            .map_err(|_| ContractError::StorageError)?;
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
pub fn set_rewards_per_token(
store: &mut dyn Storage,
rewards_per_token: Vec<(String, u128)>,
) -> Result<(), ContractError> {
rewards_per_token.iter().for_each(|item| {
REWARDS_PER_TOKEN
.save(store, &item.0, &Uint128::from(item.1))
.unwrap();
});
Ok(())
}
pub fn set_rewards_per_token(
store: &mut dyn Storage,
rewards_per_token: Vec<(String, u128)>,
) -> Result<(), ContractError> {
rewards_per_token.iter().for_each(|item| {
REWARDS_PER_TOKEN
.save(store, &item.0, &Uint128::from(item.1))
.map_err(|_| ContractError::StorageError)?;
});
Ok(())
}

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 02377c9 and 37a95f0.

Files selected for processing (1)
  • ADOs/nft-staking/src/execute.rs (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • ADOs/nft-staking/src/execute.rs

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 37a95f0 and ace9611.

Files selected for processing (2)
  • ADOs/nft-staking/src/execute.rs (1 hunks)
  • ADOs/nft-staking/src/state.rs (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • ADOs/nft-staking/src/execute.rs
  • ADOs/nft-staking/src/state.rs

@crnbarr93
Copy link
Contributor

andromedaprotocol/andromeda-core#505

Looking to resolve the issue with ContractError in execute_amp_receive in this PR.

The fix will likely require your error type to support From<AndromedaContractError>.

@oneShot0430
Copy link
Author

andromedaprotocol/andromeda-core#505

Looking to resolve the issue with ContractError in execute_amp_receive in this PR.

The fix will likely require your error type to support From<AndromedaContractError>.

I think From<AndromedaContractError> is already supported.

    #[error("{0}")]
    ADO(#[from] AndromedaContractError),

This is casting AndromedaContractError to ContractError.

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