use std::collections::HashMap;
use serde_derive::Deserialize;
use serde_derive::Serialize;
mod example;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Audit {
pub metadata: Metadata,
pub revisions: Vec<Revision>,
pub contracts: Vec<Contract>,
pub audit: AuditDetails,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
pub title: String,
pub source: String,
pub status: String,
pub languages: Vec<String>,
pub categories: Vec<String>,
pub tags: Vec<String>,
pub networks: Vec<String>,
pub timestamps: AuditTimestamps,
pub project: Project,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuditTimestamps {
pub onboarded: i64,
pub commencement: i64,
pub completion: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Project {
pub title: String,
pub website: String,
pub twitter: String,
pub github: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Revision {
pub id: String,
pub title: String,
#[serde(rename = "source.commit")]
pub source_commit: String,
pub timestamps: Timestamps,
pub status: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contract {
pub id: String,
pub revisions: HashMap<String, ContractRevisionDetails>,
pub metadata: ContractMetadata,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractRevisionDetails {
pub file: String,
pub name: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractMetadata {
pub livematch: Livematch,
pub privileged: Vec<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Livematch {
pub link: String,
pub status: String,
pub timestamps: Timestamps,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Timestamps {
pub commencement: i64,
pub completion: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuditDetails {
pub contracts: HashMap<String, ContractAudit>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractAudit {
pub description: String,
pub issues: Issues,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Issues {
pub count: i64,
pub severities: Severities,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Severities {
pub info: Info,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Info {
pub count: i64,
pub issues: Vec<Issue>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Issue {
pub id: String,
pub title: String,
pub description: String,
pub recommendation: String,
pub resolution: String,
pub status: String,
pub revisions: Revisions,
pub timestamps: Timestamps,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Revisions {
pub raised: String,
pub resolved: String,
}
#[cfg(test)]
mod tests {
use serde_json;
#[test]
fn it_works() {
let json_str = crate::example::tests::get_json();
let audit: crate::Audit = serde_json::from_str(&json_str).unwrap();
assert_eq!(audit.metadata.title, "XFarm Vaults");
assert_eq!(audit.metadata.source, "https://github.com/xfarms/vaults");
assert_eq!(audit.metadata.status, "auditing");
assert_eq!(audit.metadata.languages, vec!["solidity"]);
assert_eq!(audit.metadata.categories, vec!["vaults"]);
assert_eq!(audit.metadata.tags, vec!["medium"]);
assert_eq!(audit.metadata.networks, vec!["bsc"]);
assert_eq!(audit.metadata.timestamps.onboarded, 12312312312);
assert_eq!(audit.metadata.timestamps.commencement, 12313212312);
assert_eq!(audit.metadata.timestamps.completion, 12312321312);
assert_eq!(audit.metadata.project.title, "XFarm");
assert_eq!(audit.metadata.project.website, "https://xfarms.io");
assert_eq!(audit.metadata.project.twitter, "uno_farm");
assert_eq!(audit.metadata.project.github, "https://github.com/xfarms");
assert_eq!(audit.revisions.len(), 1);
let revision = audit.revisions[0].clone();
assert_eq!(revision.id, "preliminary");
assert_eq!(revision.title, "Preliminary");
assert_eq!(revision.source_commit, "https://github.com/xfarms/vaults/tree/4a6a247e017f96cb5f569331ca64c7f5fd41189d");
assert_eq!(revision.status, "auditing");
assert_eq!(revision.timestamps.commencement, 12312312312);
assert_eq!(revision.timestamps.completion, 1231232131);
assert_eq!(audit.contracts.len(), 1);
let contract = audit.contracts[0].clone();
assert_eq!(contract.id, "farm");
assert_eq!(contract.revisions.len(), 1);
let contract_revision = contract.revisions["preliminary"].clone();
assert_eq!(contract_revision.file, "contracts/Farm.sol");
assert_eq!(contract_revision.name, "Farm");
assert_eq!(contract.metadata.livematch.link, "https://bscscan.com/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000");
assert_eq!(contract.metadata.livematch.status, "MATCHED");
assert_eq!(contract.metadata.livematch.timestamps.commencement, 123123213);
assert_eq!(contract.metadata.livematch.timestamps.completion, 12312312312);
assert_eq!(contract.metadata.privileged.len(), 4);
assert_eq!(contract.metadata.privileged[0], "transferOwnership");
assert_eq!(contract.metadata.privileged[1], "renounceOwnership");
assert_eq!(contract.metadata.privileged[2], "pause");
assert_eq!(contract.metadata.privileged[3], "unpause");
assert_eq!(audit.audit.contracts.len(), 1);
let farm = audit.audit.contracts["farm"].clone();
assert_eq!(farm.description, "The Farm contract is responsible for blabla");
assert_eq!(farm.issues.count, 1);
assert_eq!(farm.issues.severities.info.count, 1);
assert_eq!(farm.issues.severities.info.issues.len(), 1);
let issue = farm.issues.severities.info.issues[0].clone();
assert_eq!(issue.id, "farm-typographicerrors");
assert_eq!(issue.title, "Typographic Errors");
assert_eq!(issue.description, "The contract contains the following typographic errors:\n\nLine 3\n ```uint256 precsicion```");
assert_eq!(issue.recommendation, "Consider resolving the aforementioned errors.");
assert_eq!(issue.resolution, "");
assert_eq!(issue.status, "pending");
assert_eq!(issue.revisions.raised, "preliminary");
assert_eq!(issue.revisions.resolved, "resolutions1");
assert_eq!(issue.timestamps.commencement, 12312321);
assert_eq!(issue.timestamps.completion, 123123123);
}
}