auditfile/
lib.rs

1use std::collections::HashMap;
2
3use serde_derive::Deserialize;
4use serde_derive::Serialize;
5
6mod example;
7
8#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Audit {
11    pub metadata: Metadata,
12    pub revisions: Vec<Revision>,
13    pub contracts: Vec<Contract>,
14    pub audit: AuditDetails,
15}
16
17#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
18#[serde(rename_all = "camelCase")]
19pub struct Metadata {
20    pub title: String,
21    pub source: String,
22    pub status: String,
23    pub languages: Vec<String>,
24    pub categories: Vec<String>,
25    pub tags: Vec<String>,
26    pub networks: Vec<String>,
27    pub timestamps: AuditTimestamps,
28    pub project: Project,
29}
30
31#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct AuditTimestamps {
34    pub onboarded: i64,
35    pub commencement: i64,
36    pub completion: i64,
37}
38
39#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct Project {
42    pub title: String,
43    pub website: String,
44    pub twitter: String,
45    pub github: String,
46}
47
48#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub struct Revision {
51    pub id: String,
52    pub title: String,
53    #[serde(rename = "source.commit")]
54    pub source_commit: String,
55    pub timestamps: Timestamps,
56    pub status: String,
57}
58
59#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
60#[serde(rename_all = "camelCase")]
61pub struct Contract {
62    pub id: String,
63    pub revisions: HashMap<String, ContractRevisionDetails>,
64    pub metadata: ContractMetadata,
65}
66
67#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct ContractRevisionDetails {
70    pub file: String,
71    pub name: String,
72}
73
74#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct ContractMetadata {
77    pub livematch: Livematch,
78    pub privileged: Vec<String>,
79}
80
81#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct Livematch {
84    pub link: String,
85    pub status: String,
86    pub timestamps: Timestamps,
87}
88
89#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
90#[serde(rename_all = "camelCase")]
91pub struct Timestamps {
92    pub commencement: i64,
93    pub completion: i64,
94}
95
96#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
97#[serde(rename_all = "camelCase")]
98pub struct AuditDetails {
99    pub contracts: HashMap<String, ContractAudit>,
100}
101
102#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
103#[serde(rename_all = "camelCase")]
104pub struct ContractAudit {
105    pub description: String,
106    pub issues: Issues,
107}
108
109#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct Issues {
112    pub count: i64,
113    pub severities: Severities,
114}
115
116#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct Severities {
119    pub info: Info,
120}
121
122#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
123#[serde(rename_all = "camelCase")]
124pub struct Info {
125    pub count: i64,
126    pub issues: Vec<Issue>,
127}
128
129#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
130#[serde(rename_all = "camelCase")]
131pub struct Issue {
132    pub id: String,
133    pub title: String,
134    pub description: String,
135    pub recommendation: String,
136    pub resolution: String,
137    pub status: String,
138    pub revisions: Revisions,
139    pub timestamps: Timestamps,
140}
141
142#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
143#[serde(rename_all = "camelCase")]
144pub struct Revisions {
145    pub raised: String,
146    pub resolved: String,
147}
148
149
150
151#[cfg(test)]
152mod tests {
153    use serde_json;
154
155    #[test]
156    fn it_works() {
157        let json_str = crate::example::tests::get_json();
158        let audit: crate::Audit = serde_json::from_str(&json_str).unwrap();
159        assert_eq!(audit.metadata.title, "XFarm Vaults");
160        assert_eq!(audit.metadata.source, "https://github.com/xfarms/vaults");
161        assert_eq!(audit.metadata.status, "auditing");
162        assert_eq!(audit.metadata.languages, vec!["solidity"]);
163        assert_eq!(audit.metadata.categories, vec!["vaults"]);
164        assert_eq!(audit.metadata.tags, vec!["medium"]);
165        assert_eq!(audit.metadata.networks, vec!["bsc"]);
166        assert_eq!(audit.metadata.timestamps.onboarded, 12312312312);
167        assert_eq!(audit.metadata.timestamps.commencement, 12313212312);
168        assert_eq!(audit.metadata.timestamps.completion, 12312321312);
169        assert_eq!(audit.metadata.project.title, "XFarm");
170        assert_eq!(audit.metadata.project.website, "https://xfarms.io");
171        assert_eq!(audit.metadata.project.twitter, "uno_farm");
172        assert_eq!(audit.metadata.project.github, "https://github.com/xfarms");
173        assert_eq!(audit.revisions.len(), 1);
174        let revision = audit.revisions[0].clone();
175        assert_eq!(revision.id, "preliminary");
176        assert_eq!(revision.title, "Preliminary");
177        assert_eq!(revision.source_commit, "https://github.com/xfarms/vaults/tree/4a6a247e017f96cb5f569331ca64c7f5fd41189d");
178        assert_eq!(revision.status, "auditing");
179        assert_eq!(revision.timestamps.commencement, 12312312312);
180        assert_eq!(revision.timestamps.completion, 1231232131);
181
182        assert_eq!(audit.contracts.len(), 1);
183        let contract = audit.contracts[0].clone();
184        assert_eq!(contract.id, "farm");
185        assert_eq!(contract.revisions.len(), 1);
186        let contract_revision = contract.revisions["preliminary"].clone();
187        assert_eq!(contract_revision.file, "contracts/Farm.sol");
188        assert_eq!(contract_revision.name, "Farm");
189        assert_eq!(contract.metadata.livematch.link, "https://bscscan.com/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000");
190        assert_eq!(contract.metadata.livematch.status, "MATCHED");
191        assert_eq!(contract.metadata.livematch.timestamps.commencement, 123123213);
192        assert_eq!(contract.metadata.livematch.timestamps.completion, 12312312312);
193        assert_eq!(contract.metadata.privileged.len(), 4);
194        assert_eq!(contract.metadata.privileged[0], "transferOwnership");
195        assert_eq!(contract.metadata.privileged[1], "renounceOwnership");
196        assert_eq!(contract.metadata.privileged[2], "pause");
197        assert_eq!(contract.metadata.privileged[3], "unpause");
198
199        assert_eq!(audit.audit.contracts.len(), 1);
200        let farm = audit.audit.contracts["farm"].clone();
201        assert_eq!(farm.description, "The Farm contract is responsible for blabla");
202        assert_eq!(farm.issues.count, 1);
203        assert_eq!(farm.issues.severities.info.count, 1);
204        assert_eq!(farm.issues.severities.info.issues.len(), 1);
205        let issue = farm.issues.severities.info.issues[0].clone();
206        assert_eq!(issue.id, "farm-typographicerrors");
207        assert_eq!(issue.title, "Typographic Errors");
208        assert_eq!(issue.description, "The contract contains the following typographic errors:\n\nLine 3\n ```uint256 precsicion```");
209        assert_eq!(issue.recommendation, "Consider resolving the aforementioned errors.");
210        assert_eq!(issue.resolution, "");
211        assert_eq!(issue.status, "pending");
212        assert_eq!(issue.revisions.raised, "preliminary");
213        assert_eq!(issue.revisions.resolved, "resolutions1");
214        assert_eq!(issue.timestamps.commencement, 12312321);
215        assert_eq!(issue.timestamps.completion, 123123123);
216    }
217}