pub mod declaration;
mod json;
use crate::{function::Selector, primitive::Word, value::ValueKind};
use ethprim::Hasher;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display, Formatter, Write as _};
pub type Abi = Vec<Descriptor>;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
pub enum Descriptor {
Function(FunctionDescriptor),
Constructor(ConstructorDescriptor),
Receive,
Fallback(StateMutability),
Event(EventDescriptor),
Error(ErrorDescriptor),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
pub struct FunctionDescriptor {
pub name: String,
pub inputs: Vec<Parameter>,
pub outputs: Vec<Parameter>,
pub state_mutability: StateMutability,
}
impl FunctionDescriptor {
pub fn canonical(&self) -> Canonical<'_, Self> {
Canonical(self)
}
pub fn signature(&self) -> Signature<'_> {
Signature(self)
}
pub fn selector(&self) -> Selector {
let mut hasher = Hasher::new();
write!(&mut hasher, "{}", self.canonical()).unwrap();
selector(hasher)
}
}
impl Display for Canonical<'_, FunctionDescriptor> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(&self.0.name)?;
fmt_fields(f, &self.0.inputs)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
pub struct ConstructorDescriptor {
pub inputs: Vec<Parameter>,
pub state_mutability: StateMutability,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
pub struct EventDescriptor {
pub name: String,
pub inputs: Vec<EventField>,
pub anonymous: bool,
}
impl EventDescriptor {
pub fn canonical(&self) -> Canonical<'_, Self> {
Canonical(self)
}
pub fn selector(&self) -> Option<Word> {
if self.anonymous {
return None;
}
let mut hasher = Hasher::new();
write!(&mut hasher, "{}", self.canonical()).unwrap();
Some(topic(hasher))
}
}
impl Display for Canonical<'_, EventDescriptor> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(&self.0.name)?;
fmt_fields(f, &self.0.inputs)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
pub struct ErrorDescriptor {
pub name: String,
pub inputs: Vec<Field>,
}
impl ErrorDescriptor {
pub fn canonical(&self) -> Canonical<'_, Self> {
Canonical(self)
}
pub fn selector(&self) -> Selector {
let mut hasher = Hasher::new();
write!(&mut hasher, "{}", self.canonical()).unwrap();
selector(hasher)
}
}
impl Display for Canonical<'_, ErrorDescriptor> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(&self.0.name)?;
fmt_fields(f, &self.0.inputs)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Field", into = "json::Field")]
pub struct Field {
pub name: String,
pub kind: ValueKind,
pub components: Option<Vec<Field>>,
pub internal_type: Option<String>,
}
impl Display for Canonical<'_, Field> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0.kind)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Field", into = "json::Field")]
pub struct Parameter {
pub field: Field,
pub kind_name: Option<String>,
}
impl Display for Canonical<'_, Parameter> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match &self.0.kind_name {
Some(kind_name) => f.write_str(kind_name),
None => write!(f, "{}", Canonical(&self.0.field)),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(try_from = "json::Field", into = "json::Field")]
pub struct EventField {
pub field: Field,
pub indexed: bool,
}
impl Display for Canonical<'_, EventField> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", Canonical(&self.0.field))
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum StateMutability {
Pure,
View,
NonPayable,
Payable,
}
impl StateMutability {
fn with_flags(constant: bool, payable: bool) -> StateMutability {
match (constant, payable) {
(_, true) => Self::Payable,
(false, _) => Self::NonPayable,
(true, _) => Self::View,
}
}
}
pub struct Canonical<'a, T>(&'a T);
pub struct Signature<'a>(&'a FunctionDescriptor);
impl Display for Signature<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}:", Canonical(self.0))?;
fmt_fields(f, &self.0.outputs)
}
}
fn fmt_fields<'a, T, I>(f: &mut Formatter, fields: I) -> fmt::Result
where
T: 'a,
Canonical<'a, T>: Display,
I: IntoIterator<Item = &'a T> + 'a,
{
f.write_str("(")?;
for (i, field) in fields.into_iter().enumerate() {
if i != 0 {
f.write_str(",")?;
}
write!(f, "{}", Canonical(field))?;
}
f.write_str(")")
}
fn selector(hasher: Hasher) -> Selector {
let digest = hasher.finalize();
Selector(digest[..4].try_into().unwrap())
}
fn topic(hasher: Hasher) -> [u8; 32] {
*hasher.finalize()
}
#[cfg(test)]
mod tests {
use super::*;
use hex_literal::hex;
#[test]
fn function_selector() {
let function =
FunctionDescriptor::parse_declaration("function transfer(address to, uint value)")
.unwrap();
assert_eq!(function.selector(), hex!("a9059cbb"));
}
#[test]
fn function_signature() {
let function = FunctionDescriptor::parse_declaration(
"function transfer(address to, uint value) returns (bool)",
)
.unwrap();
assert_eq!(
function.signature().to_string(),
"transfer(address,uint256):(bool)",
);
}
#[test]
fn event_selector() {
let event = EventDescriptor::parse_declaration(
"event Transfer(address indexed to, address indexed from, uint256 value)",
)
.unwrap();
assert_eq!(
event.selector().unwrap(),
hex!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
);
}
#[test]
fn anonymous_event_selector() {
let event = EventDescriptor::parse_declaration("event Foo() anonymous").unwrap();
assert!(event.selector().is_none());
}
#[test]
fn error_selector() {
let error = ErrorDescriptor::parse_declaration("error Error(string message)").unwrap();
assert_eq!(error.selector(), hex!("08c379a0"));
}
}