Introduction
We express our gratitude to the Seedworld team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Seedworld is a free-to-play UGC gaming platform where players create games, build worlds, and trade in a blockchain-powered fantasy metaverse with a resource-driven economy and sustainable creator ecosystem.
Document | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for Seedworld |
| Audited By | Seher Saylik |
| Approved By | Ivan Bondar |
| Website | https://seedworld.io/→ |
| Changelog | 27/02/2025 - Preliminary Report |
| 06/03/2025 - Final Report | |
| Platform | Ethereum |
| Language | Solidity |
| Tags | Non-fungible Token (NFT); NFT Staking |
| Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Seedworld
- Audited By
- Seher Saylik
- Approved By
- Ivan Bondar
- Website
- https://seedworld.io/→
- Changelog
- 27/02/2025 - Preliminary Report
- 06/03/2025 - Final Report
- Platform
- Ethereum
- Language
- Solidity
- Tags
- Non-fungible Token (NFT); NFT Staking
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
|---|---|
| Repository | https://github.com/SeedworldStudios/product-evm-contracts/tree/main/contracts/land-management→ |
| Commit | bbd5bad973122c9b8cddb8e42b83d4a8ee348995 |
| Retest | 3d3d9813663563b635318cd8dee3176a65b15673 |
Review Scope
- Commit
- bbd5bad973122c9b8cddb8e42b83d4a8ee348995
- Retest
- 3d3d9813663563b635318cd8dee3176a65b15673
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are partially provided.
Technical description is not provided.
Code quality
The development environment is configured.
Test coverage
Code coverage of the project is 69.49% (branch coverage).
Deployment and basic user interactions are covered with tests.
Different stake extending scenarios are not tested entirely.
Interactions by several users are not tested thoroughly.
System Overview
Seedworld is an NFT-based staking protocol designed for managing virtual land assets. It comprises the following primary contracts:
LandNFT — an upgradeable ERC721A-based NFT contract for managing Land NFTs. It includes advanced features such as EIP-712 signature verification for authorized minting, role-based access control, royalty management via ERC2981, and configurable metadata through base URI settings. This contract enables the creation and management of multiple NFT types representing virtual land parcels, while ensuring that minting requests are validated through secure off-chain signatures.
NFTStaking — a contract that allows users to stake their LandNFT tokens for a predefined or dynamic duration. It supports two staking modes:
Fixed Duration Staking: Users can stake NFTs using preset duration values. The contract validates the duration against a list of allowed fixed durations.
Dynamic Duration Staking: Users can stake NFTs with a flexible duration, provided the chosen duration falls within an allowed range.
PaymentGateway — contract that enables users to make payments using either whitelisted ERC20 tokens or native ETH, transferring the funds securely to a designated safe wallet after validating payment details like token balance and expiry time.
Privileged roles
The DEFAULTADMINROLE in the LandNFT:
add new NFT types and update existing ones.
configure the base URI
sets the user NFT type hash
set validator address
set max supply
configure the royalty settings
The DEFAULTADMINROLE in the NFTStaking can:
add/remove fixed staking durations
set the dynamic stake range
enable/disable dynamic or fixed stakings
set NFT address
set max tokens
The DEFAULTADMINROLE in the PaymentGate can:
set safe wallet
whitelist/blacklist a token
withdraw native/ERC20 tokens to safeWallet address
Potential Risks
The NFTStaking contract is designed solely for NFT staking functionality and intentionally does not include any built-in reward mechanism. As a result, any reward distribution, incentive structure, or related reward mechanism is explicitly out of scope for this contract’s design and implementation.
Inconsistent and evolving requirements during the audit have introduced uncertainties regarding the intended functionality and security posture of the solution. This variability may result in potential gaps or misalignments that could affect the system's reliability and security, underscoring the need for clearer specifications and formal change management procedures.
The owner's ability to modify royalty settings even after NFTs are minted creates a risk that users may face unexpected changes to their revenue streams from secondary sales, potentially undermining trust and expected returns.
Administrative Key Control Risks: The digital contract architecture relies on administrative keys for critical operations. Centralized control over these keys presents a significant security risk, as compromise or misuse can lead to unauthorized actions or loss of funds.
Flexibility and Risk in Contract Upgrades: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides flexibility in addressing issues and evolving the project, it also introduces risks if upgrade processes are not properly managed or secured, potentially allowing for unauthorized changes that could compromise the project's integrity and security.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2025-1085 | Incorrect Duration Calculation for Active Stakes | fixed | High | |
| F-2025-1085 | Unpreserved Accrued Staking Duration on Stake Extension | fixed | High | |
| F-2025-1085 | NFT Address Update Vulnerability Enabling Malicious Contract Replacement | fixed | Medium | |
| F-2025-1084 | Unrestricted Admin Control over Royalty Settings | accepted | Medium | |
| F-2025-1085 | Unsafe ERC20 Transfer in sweepERC20Tokens Function | fixed | Low | |
| F-2025-1085 | Initializer Is Not Disabled In constructor | fixed | Low | |
| F-2025-1085 | Potential Denial-of-Service (DoS) via Unbounded Loop Iterations | mitigated | Low | |
| F-2025-1085 | Gas Inefficiencient Error Handling and Mixing Custom Errors with Require Statements | fixed | Observation | |
| F-2025-1085 | Missing Empty NFT Type Validation | fixed | Observation | |
| F-2025-1084 | Lack of Check in setMaxSupply | fixed | Observation |
Appendix 1. Definitions
Severities
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
|---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
Potential Risks
The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
|---|---|
| Repository | https://github.com/SeedworldStudios/product-evm-contracts/tree/main/contracts/land-management→ |
| Commit | bbd5bad973122c9b8cddb8e42b83d4a8ee348995 |
| Retest | 3d3d9813663563b635318cd8dee3176a65b15673 |
| Whitepaper | N/A |
| Requirements | Submitted as a zip file. |
| Technical Requirements | N/A |
Scope Details
- Commit
- bbd5bad973122c9b8cddb8e42b83d4a8ee348995
- Retest
- 3d3d9813663563b635318cd8dee3176a65b15673
- Whitepaper
- N/A
- Requirements
- Submitted as a zip file.
- Technical Requirements
- N/A
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Seedworld, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Foundry, a tool used for fuzz-testing, was employed to check how the protocol behaves under various inputs. Due to the complex and dynamic interactions within the protocol, unexpected edge cases might arise. Therefore, it was important to use fuzz-testing to ensure that several system invariants hold true in all situations.
Fuzz-testing allows the input of many random data points into the system, helping to identify issues that regular testing might miss. A specific Echidna fuzzing suite was prepared for this task, and throughout the assessment, 10 invariants were tested over 10,000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
|---|---|---|
LandNFT::getMaxNFTCount() Valid inputs return the expected result and invalid inputs revert. | Passed | 10k |
LandNFT::addNFTTypes Unique, non-empty NFT type strings are successfully added and registered in the contract. | Passed | 10k |
LandNFT::toString() The internal toString function returns the correct decimal string representation for any uint256 value. | Passed | 10k |
LandNFT::mintNFT() When processing multiple valid mint requests with proper signatures, the contract correctly updates the total supply. | Passed | 10k |
LandNFT::mintNFT Duplicate signatures (attempted replay attacks) are rejected, ensuring each mint request is unique. | Passed | 10k |
NFTStaking::stakeNFTsFixedDuration() – invalid durations revert with InvalidFixedDuration. | Passed | 10k |
NFTStaking::extendStakeDuration() – If the remaining time plus the extension exceeds the maximum allowed, it reverts . | Passed | 10k |
NFTStaking::stakeNFTDynamicDuration() – Inputs within the allowed dynamic range succeed, while out-of-range inputs revert. | Passed | 10k |
NFTStaking::stakeNFTFixedDuration() – Inputs within the allowed fixed range succeed, while out-of-range inputs revert. | Passed | 10k |
NFTStaking::unstakeNFTs() – Unstaking before the staking period ends reverts with StakingNotEnded. | Passed | 10k |
Invariant
LandNFT::getMaxNFTCount()Valid inputs return the expected result and invalid inputs revert.Test Result
- Passed
Run Count
- 10k
Invariant
LandNFT::addNFTTypesUnique, non-empty NFT type strings are successfully added and registered in the contract.Test Result
- Passed
Run Count
- 10k
Invariant
LandNFT::toString()The internal toString function returns the correct decimal string representation for any uint256 value.Test Result
- Passed
Run Count
- 10k
Invariant
LandNFT::mintNFT()When processing multiple valid mint requests with proper signatures, the contract correctly updates the total supply.Test Result
- Passed
Run Count
- 10k
Invariant
LandNFT::mintNFTDuplicate signatures (attempted replay attacks) are rejected, ensuring each mint request is unique.Test Result
- Passed
Run Count
- 10k
Invariant
NFTStaking::stakeNFTsFixedDuration()– invalid durations revert with InvalidFixedDuration.Test Result
- Passed
Run Count
- 10k
Invariant
NFTStaking::extendStakeDuration()– If the remaining time plus the extension exceeds the maximum allowed, it reverts .Test Result
- Passed
Run Count
- 10k
Invariant
NFTStaking::stakeNFTDynamicDuration()– Inputs within the allowed dynamic range succeed, while out-of-range inputs revert.Test Result
- Passed
Run Count
- 10k
Invariant
NFTStaking::stakeNFTFixedDuration()– Inputs within the allowed fixed range succeed, while out-of-range inputs revert.Test Result
- Passed
Run Count
- 10k
Invariant
NFTStaking::unstakeNFTs()– Unstaking before the staking period ends reverts with StakingNotEnded.Test Result
- Passed
Run Count
- 10k
Additional Recommendations
The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.
To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:
Detecting changes to ownership or critical permissions.
Monitoring large or unexpected transactions and minting events.
Pausing operations when irregularities are identified.
These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.