-
Notifications
You must be signed in to change notification settings - Fork 0
V2 #2
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
Conversation
- add get_contracts_by_code_hash() to find verified contracts by hash - add get_contracts_count() to return total verified contracts - add unit tests for new functions - update rust toolchain to 1.85.0 - update dependencies
V2 feat update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request introduces significant foundational changes to transform the verifier contract into a comprehensive verification registry with social features. The main purpose is to add voting and commenting capabilities to verified contracts while modernizing the codebase with updated dependencies and build configurations.
Key Changes:
- New data models for votes and comments on verified contracts with custom serialization for timestamps
- Simplified contract verification model removing GitHub metadata and build configuration fields
- Updated dependencies (near-sdk 5.2.1) and Rust toolchain (1.85.0) with reproducible build support
Reviewed changes
Copilot reviewed 9 out of 11 changed files in this pull request and generated 22 comments.
Show a summary per file
| File | Description |
|---|---|
src/verified_contract/vote.rs |
Introduces Vote and VoteType structs with custom equality/ordering logic for tracking user votes |
src/verified_contract/comment.rs |
Defines Comment struct for storing user comments with votes and timestamps |
src/verified_contract/mod.rs |
Declares VerifiedContract struct with simplified fields and collections for votes/comments |
src/str_serializers.rs |
Provides custom serializers for u64/u128 to ensure numeric fields serialize as strings in JSON |
src/lib.rs |
Major refactor adding voting/commenting methods, updating contract storage structure, and simplifying verification data |
tests/test_basics.rs |
Updates integration test to initialize contract and removes obsolete assertions for removed fields |
Cargo.toml |
Updates dependencies to near-sdk 5.2.1, adds reproducible build configuration with Docker image metadata |
rust-toolchain.toml |
Updates Rust version from 1.73.0 to 1.85.0 |
.vscode/settings.json |
Adds Rust Analyzer configuration for the project |
.gitignore |
Adds entries for backups and build scripts |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
| self.contracts.insert(&account_id, &contract); | ||
| log!("Vote updated for contract {}", account_id); | ||
| } | ||
|
|
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The add_comment public function lacks documentation. Users need to understand:
- Maximum comment length (if any)
- Whether empty comments are allowed
- What the comment ID will be and how to reference it
Solution: Add documentation:
/// Adds a comment to a verified contract.
///
/// # Arguments
/// * `account_id` - The account ID of the contract to comment on
/// * `content` - The text content of the comment
///
/// # Panics
/// Panics if the contract is not found
pub fn add_comment(&mut self, account_id: AccountId, content: String) {| /// Adds a comment to a verified contract. | |
| /// | |
| /// # Arguments | |
| /// * `account_id` - The account ID of the contract to comment on. | |
| /// * `content` - The text content of the comment. | |
| /// | |
| /// # Details | |
| /// - Maximum comment length: No explicit limit is enforced in this function. | |
| /// - Empty comments: Allowed (no explicit check). | |
| /// - Comment ID: The comment ID is assigned as the current number of comments (`self.comments.len() as u64`). | |
| /// You can reference a comment by its ID as returned in the `Comment` struct. | |
| /// | |
| /// # Panics | |
| /// Panics if the contract is not found for the given `account_id`. |
|
|
||
| return (filtered, pages); | ||
| } | ||
|
|
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vote_comment public function lacks documentation. Users need to understand:
- How to obtain comment IDs
- What happens if they vote multiple times
- Whether the comment must exist
Solution: Add documentation:
/// Adds or updates a vote for a comment.
/// If the user has already voted on this comment, their previous vote is replaced.
///
/// # Arguments
/// * `comment_id` - The ID of the comment to vote on
/// * `is_upvote` - true for upvote, false for downvote
///
/// # Panics
/// Panics if the comment is not found
pub fn vote_comment(&mut self, comment_id: u64, is_upvote: bool) {| /// Adds or updates a vote for a comment. | |
| /// | |
| /// # Arguments | |
| /// * `comment_id` - The ID of the comment to vote on. You can obtain comment IDs using the `get_comments` method. | |
| /// * `is_upvote` - `true` for upvote, `false` for downvote. | |
| /// | |
| /// # Behavior | |
| /// If the caller has already voted on this comment, their previous vote is replaced with the new one. | |
| /// | |
| /// # Panics | |
| /// Panics if the comment with the given ID does not exist. |
| pub code_hash: String, | ||
| pub block_height: u64, | ||
| pub votes: HashSet<Vote>, | ||
| pub comments: Vec<u64>, |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The field name comments is misleading as it stores comment IDs (Vec<u64>), not actual Comment objects. This could confuse developers who might expect to access comment data directly.
Solution: Rename the field to better reflect its purpose, such as comment_ids or comment_references:
pub comment_ids: Vec<u64>,| pub comments: Vec<u64>, | |
| pub comment_ids: Vec<u64>, |
| let mut result: Vec<(AccountId, VerifiedContract)> = Vec::new(); | ||
|
|
||
| for (k, v) in self.contracts.iter() { | ||
| if k.as_str() | ||
| .to_lowercase() | ||
| .replace(".testnet", "") | ||
| .replace(".near", "") | ||
| .contains(&key.to_lowercase()) | ||
| { | ||
| result.push((k, v)); | ||
| } | ||
| } | ||
|
|
||
| let pages: u64 = self.get_pages(result.len() as u64, limit as u64); | ||
| let filtered: Vec<(AccountId, ContractData)> = result | ||
| .into_iter() | ||
| .skip(from_index) | ||
| .take(limit) | ||
| .collect(); | ||
| let filtered: Vec<(AccountId, VerifiedContract)> = | ||
| result.into_iter().skip(from_index).take(limit).collect(); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The search function iterates through all contracts before applying pagination. This is inefficient for large datasets because:
- It collects all matching results into a vector (line 139-150)
- Then applies skip/take pagination (line 154)
This means if there are 10,000 matching contracts but you only want page 1 with 10 results, it still processes all 10,000 entries.
Solution: Consider applying pagination during iteration:
let filtered: Vec<(AccountId, VerifiedContract)> = self.contracts
.iter()
.filter(|(k, _)| {
k.as_str()
.to_lowercase()
.replace(".testnet", "")
.replace(".near", "")
.contains(&key.to_lowercase())
})
.skip(from_index)
.take(limit)
.collect();Note: You'll need to count total matches separately for accurate page calculation.
| pub fn vote_contract(&mut self, account_id: AccountId, is_upvote: bool) { | ||
| let mut contract: VerifiedContract = self | ||
| .contracts | ||
| .get(&account_id) | ||
| .unwrap_or_else(|| panic!("Contract {} not found", account_id)) | ||
| .into(); | ||
|
|
||
| self.update_or_insert_vote(&mut contract.votes, is_upvote); | ||
|
|
||
| self.contracts.insert(&account_id, &contract); | ||
| log!("Vote updated for contract {}", account_id); | ||
| } |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vote_contract function lacks test coverage for the error case where a user tries to vote on a non-existent contract. The function will panic with "Contract {} not found", but there's no test verifying this behavior.
Solution: Add a test case:
#[test]
#[should_panic(expected = "Contract")]
fn test_vote_nonexistent_contract() {
let context = get_context(accounts(0));
testing_env!(context.build());
let mut contract = SourceScan::new();
contract.vote_contract(accounts(1), true); // Should panic
}| pub fn set_contract( | ||
| &mut self, | ||
| account_id: AccountId, | ||
| cid: String, | ||
| code_hash: String, | ||
| block_height: u64, | ||
| lang: String, | ||
| ) { |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing input validation for string parameters in set_contract. The function accepts:
cid: Content identifier (could be empty or malformed)code_hash: Hash of the contract code (should have specific format/length)lang: Programming language (could be empty or invalid)
Without validation, invalid data could be stored, making the contract data unreliable.
Solution: Add validation:
require!(!cid.trim().is_empty(), "CID cannot be empty");
require!(!code_hash.trim().is_empty(), "Code hash cannot be empty");
require!(!lang.trim().is_empty(), "Language cannot be empty");
// Optionally validate format/length constraints| use std::hash::{Hash, Hasher}; | ||
|
|
||
| #[near(serializers=[borsh, json])] | ||
| #[derive(PartialOrd, Eq, PartialEq, Clone)] |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The VoteType enum derives PartialOrd (line 7) but implements Ord manually (lines 45-55). Since Ord is a supertrait of PartialOrd, the derived PartialOrd implementation will be overridden by the blanket implementation impl<T: Ord> PartialOrd for T. However, having both the derive and manual implementation is confusing.
Solution: Remove PartialOrd from the derive macro on line 7, leaving only the manual Ord implementation (which automatically provides PartialOrd).
| #[derive(PartialOrd, Eq, PartialEq, Clone)] | |
| #[derive(Eq, PartialEq, Clone)] |
|
|
||
| [package.metadata.near.reproducible_build] | ||
| # docker image, descriptor of build environment | ||
| image = "sourcescan/cargo-near:0.17.0-rust-1.86.0" |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Docker image references Rust 1.86.0, but rust-toolchain.toml specifies Rust 1.85.0. This mismatch could lead to inconsistent build results between local development and Docker-based reproducible builds.
Solution: Update the image name to match the toolchain version (change 1.86.0 to 1.85.0), or update rust-toolchain.toml to use 1.86.0 if that's the intended version.
| image = "sourcescan/cargo-near:0.17.0-rust-1.86.0" | |
| image = "sourcescan/cargo-near:0.17.0-rust-1.85.0" |
| near-workspaces = { version = "0.9.0", default-features = false, features = ["install", "unstable"] } | ||
| tokio = { version = "1.12.0", features = ["full"] } | ||
| serde_json = "1" | ||
| near-sdk = { version = "5.1.0", features = ["unit-testing"] } |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dev-dependencies specify near-sdk = "5.1.0" while the main dependencies use near-sdk = "5.2.1". This version mismatch can cause compilation issues or unexpected behavior in tests, as the testing features might be compiled against a different version than the production code.
Solution: Update the dev-dependencies to use the same version as the main dependencies: near-sdk = { version = "5.2.1", features = ["unit-testing"] }
| near-sdk = { version = "5.1.0", features = ["unit-testing"] } | |
| near-sdk = { version = "5.2.1", features = ["unit-testing"] } |
| @@ -0,0 +1,6 @@ | |||
| { | |||
| "rust-analyzer.linkedProjects": [ | |||
| "./Cargo.toml", | |||
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The linkedProjects array contains duplicate entries of "./Cargo.toml". This is redundant and serves no purpose.
Solution: Remove one of the duplicate entries:
"rust-analyzer.linkedProjects": [
"./Cargo.toml"
]| "./Cargo.toml", |
This pull request introduces several foundational changes to the project, focusing on contract data modeling, serialization utilities, and build configuration updates. The main highlights are the addition of new modules for handling votes and comments within verified contracts, custom serialization logic for numeric types, and updates to dependencies and toolchain versions for improved compatibility and reproducibility.
Data Model Enhancements
src/verified_contract/vote.rsandsrc/verified_contract/comment.rs, introducingVote,VoteType, andCommentstructs for tracking votes and comments on verified contracts, including custom equality, ordering, and hashing logic for votes. [1] [2]src/verified_contract/mod.rsto define theVerifiedContractstruct, which now includes votes and comments, and to expose the new modules.Serialization Utilities
src/str_serializers.rswith custom serialization/deserialization logic foru64andu128types, ensuring numeric fields are stored as strings in JSON.timestampfields in votes and comments. [1] [2]Build and Dependency Updates
Cargo.toml:near-sdkand related dependencies to newer versions.rust-toolchain.tomlto use Rust 1.85.0 for better compatibility..vscode/settings.jsonfor Rust Analyzer project configuration.Test Adjustments
ContractDatastruct in tests and updated the operational test to initialize the contract before other calls. [1] [2] [3]