Skip to content

Commit

Permalink
Add ERC20ContractHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
yanganto committed May 14, 2021
1 parent b78768c commit 671c05d
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
with:
nix_path: nixpkgs=channel:nixos-unstable
- run: nix-shell --run "cargo clippy"
- run: nix-shell --run "cargo test"
- run: nix-shell --run "cargo test --all-features"
12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ edition = "2018"
build="build.rs"

[dependencies]
thiserror = "1.0.24"
anyhow = "1.0.40"
serde = "1.0"
serde_derive = "1.0"
toml = "0.5.8"
ewasm_api = { version = "0.11", features = ["std", "qimalloc"] }

ethereum-types = { optional = true, features = ["serialize"], git = "https://github.com/paritytech/parity-common.git", rev = "0867e488f6567e0d7fe13e78a14797ff019033f7" }

[build-dependencies]
cmake = "0.1.42"

[features]
default = []
token = ["ethereum-types"]
11 changes: 4 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
#[cfg(feature = "token")]
pub mod token;
#[cfg(feature = "token")]
pub use token::*;
69 changes: 69 additions & 0 deletions src/token/erc20.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! ERC20 contract handler
//! The handler helps you deploy/generate ERC20 token, just like manipulating a
//! database.
//!
//! The general way we connect to a DB is to use the connection string
//! > postgres://user:password@127.0.0.1:5432
//!
//! This handler mimic the database connecting way for ERC20 contract, and
//! automatically deploy the contract if needed
//! >>>
//! erc20://sender_address@node_ip:node_port/ERC20_contract_config_file_path
//! erc20://sender_address@node_ip:node_port/contract_address
//! >>>

use crate::token::errors::ContractError as Error;
use anyhow::Result;
use ethereum_types::Address;
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

/// ERC20ContractHandler helps you deploy or interactive with the existing
/// ERC 20 contract
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct ERC20ContractHandler {
/// The contract address, when the contract is not deployed,
/// the `connect` function called the contract will be automatically
/// deployed and the address field of the config will be filled
pub address: Option<Address>,

#[serde(skip_serializing)]
/// The contract data in hex literal for eWasm binary, or a file path to
/// the .ewasm file
pub call_data: Option<String>,

/// If the ERC20_contract_config_file_path pass from the connection string,
/// this field will be filled
#[serde(skip)]
pub(crate) config_file_path: Option<PathBuf>,
}

impl ERC20ContractHandler {
/// Reach the contract, if the contract is not exist, then deploy it first
pub fn connect(&mut self) -> Result<()> {
if self.address.is_none() {
return self.deploy();
}
Ok(())
}

/// deploy the contract from call data store contract address into config
fn deploy(&mut self) -> Result<()> {
if let Some(_config_file_path) = self.config_file_path.take() {
if let Some(call_data) = self.call_data.take() {
if let Some(call_data) = ERC20ContractHandler::get_call_data(call_data) {
if call_data.len() < 4 {
return Err(Error::ContractSizeError(call_data.len()).into());
}
return Ok(());
}
}
return Err(Error::InsufficientContractInfoError.into());
}
panic!("config_file_path should be update when ERC20ContractHandler construct")
}
/// Return the call data binary from hex literal or from a ewasm file
fn get_call_data(_call_data_info: String) -> Option<Vec<u8>> {
Some(vec![0, 0])
}
}
9 changes: 9 additions & 0 deletions src/token/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
#[error("the size of contract `{0}` is not correct")]
ContractSizeError(usize),
#[error("contract address and call data are both absent")]
InsufficientContractInfoError,
}
5 changes: 5 additions & 0 deletions src/token/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod erc20;
pub mod errors;

#[cfg(test)]
mod tests;
56 changes: 56 additions & 0 deletions src/token/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::erc20::ERC20ContractHandler;
use crate::errors::ContractError as Error;
use ethereum_types::H160;
use toml;

#[test]
fn test_config_serde() {
let c1 = ERC20ContractHandler {
address: Some(H160::from_low_u64_be(15)),
call_data: Some("0x12345678".into()),
..Default::default()
};
assert_eq!(
toml::to_string(&c1).unwrap(),
"address = \"0x000000000000000000000000000000000000000f\"\n"
);

let c2: ERC20ContractHandler =
toml::from_str("address = \"0x000000000000000000000000000000000000000f\"\n").unwrap();
assert_eq!(c2.address, c1.address);

let c3: ERC20ContractHandler = toml::from_str("call_data = \"0x12345678\"\n").unwrap();
assert_eq!(c3.address, None);
assert_eq!(c3.call_data.unwrap(), "0x12345678".to_string());
}

#[test]
fn test_handle_error_config() {
let mut c1 = ERC20ContractHandler {
address: None,
call_data: None,
config_file_path: Some("/path/to/config".into()),
};
let connect_result = c1.connect();
assert!(connect_result.is_err());
if let Err(error) = connect_result {
assert_eq!(
error.downcast_ref::<Error>().unwrap(),
&Error::InsufficientContractInfoError
);
}

let mut c2 = ERC20ContractHandler {
address: None,
call_data: Some("0xabcd".to_string()),
config_file_path: Some("/path/to/config".into()),
};
let connect_result = c2.connect();
assert!(connect_result.is_err());
if let Err(error) = connect_result {
assert_eq!(
error.downcast_ref::<Error>().unwrap(),
&Error::ContractSizeError(2),
);
}
}
2 changes: 1 addition & 1 deletion ssvm-evmc

0 comments on commit 671c05d

Please sign in to comment.