ethcontract_common/
contract.rs

1//! Module for reading and examining data produced by truffle.
2
3use crate::abiext::FunctionExt;
4use crate::hash::H32;
5use crate::Abi;
6use crate::{bytecode::Bytecode, DeploymentInformation};
7use ethabi::ethereum_types::H256;
8use serde::Deserializer;
9use serde::Serializer;
10use serde::{Deserialize, Serialize};
11use std::collections::{BTreeMap, HashMap};
12use std::hash::Hash;
13use std::sync::Arc;
14use web3::types::Address;
15
16/// Represents a contract data.
17#[derive(Clone, Debug, Serialize, Deserialize)]
18#[serde(default = "Contract::empty")]
19pub struct Contract {
20    /// The contract name. Unnamed contracts have an empty string as their name.
21    #[serde(rename = "contractName")]
22    pub name: String,
23    /// The contract interface.
24    #[serde(rename = "abi")]
25    pub interface: Arc<Interface>,
26    /// The contract deployment bytecode.
27    pub bytecode: Bytecode,
28    /// The contract's expected deployed bytecode.
29    #[serde(rename = "deployedBytecode")]
30    pub deployed_bytecode: Bytecode,
31    /// The configured networks by network ID for the contract.
32    pub networks: HashMap<String, Network>,
33    /// The developer documentation.
34    pub devdoc: Documentation,
35    /// The user documentation.
36    pub userdoc: Documentation,
37}
38
39/// Struct representing publicly accessible interface of a smart contract.
40#[derive(Clone, Debug, Default, PartialEq)]
41pub struct Interface {
42    /// The contract ABI
43    pub abi: Abi,
44    /// A mapping from method signature to a name-index pair for accessing
45    /// functions in the contract ABI. This is used to avoid allocation when
46    /// searching for matching functions by signature.
47    pub methods: HashMap<H32, (String, usize)>,
48    /// A mapping from event signature to a name-index pair for resolving
49    /// events in the contract ABI.
50    pub events: HashMap<H256, (String, usize)>,
51}
52
53impl<'de> Deserialize<'de> for Interface {
54    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55    where
56        D: Deserializer<'de>,
57    {
58        let abi = Abi::deserialize(deserializer)?;
59        Ok(abi.into())
60    }
61}
62
63impl Serialize for Interface {
64    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65    where
66        S: Serializer,
67    {
68        self.abi.serialize(serializer)
69    }
70}
71
72impl From<Abi> for Interface {
73    fn from(abi: Abi) -> Self {
74        Self {
75            methods: create_mapping(&abi.functions, |function| function.selector()),
76            events: create_mapping(&abi.events, |event| event.signature()),
77            abi,
78        }
79    }
80}
81
82/// Utility function for creating a mapping between a unique signature and a
83/// name-index pair for accessing contract ABI items.
84fn create_mapping<T, S, F>(
85    elements: &BTreeMap<String, Vec<T>>,
86    signature: F,
87) -> HashMap<S, (String, usize)>
88where
89    S: Hash + Eq + Ord,
90    F: Fn(&T) -> S,
91{
92    let signature = &signature;
93    elements
94        .iter()
95        .flat_map(|(name, sub_elements)| {
96            sub_elements
97                .iter()
98                .enumerate()
99                .map(move |(index, element)| (signature(element), (name.to_owned(), index)))
100        })
101        .collect()
102}
103
104impl Contract {
105    /// Creates an empty contract instance.
106    pub fn empty() -> Self {
107        Contract::with_name(String::default())
108    }
109
110    /// Creates an empty contract instance with the given name.
111    pub fn with_name(name: impl Into<String>) -> Self {
112        Contract {
113            name: name.into(),
114            interface: Default::default(),
115            bytecode: Default::default(),
116            deployed_bytecode: Default::default(),
117            networks: HashMap::new(),
118            devdoc: Default::default(),
119            userdoc: Default::default(),
120        }
121    }
122}
123
124/// A contract's network configuration.
125#[derive(Clone, Debug, Serialize, Deserialize)]
126pub struct Network {
127    /// The address at which the contract is deployed on this network.
128    pub address: Address,
129    /// The hash of the transaction that deployed the contract on this network.
130    #[serde(rename = "transactionHash")]
131    pub deployment_information: Option<DeploymentInformation>,
132}
133
134/// A contract's documentation.
135#[derive(Clone, Debug, Default, Serialize, Deserialize)]
136pub struct Documentation {
137    /// Contract documentation
138    pub details: Option<String>,
139    /// Contract method documentation.
140    pub methods: HashMap<String, DocEntry>,
141}
142
143#[derive(Clone, Debug, Default, Serialize, Deserialize)]
144/// A documentation entry.
145pub struct DocEntry {
146    /// The documentation details for this entry.
147    pub details: Option<String>,
148}