Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch #170

Merged
merged 4 commits into from
Dec 17, 2019
Merged

Patch #170

Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ construct_runtime!(
{
// Basic stuff; balances is uncallable initially.
RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},
System: system::{Module, Call, Storage, Config, Event},
System: system::{Module, Call, Storage, Event, Config},

// Must be before session.
Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
Expand All @@ -439,8 +439,8 @@ construct_runtime!(

// Consensus support.
Authorship: authorship::{Module, Call, Storage, Inherent},
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
ImOnline: im_online::{Module, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
Grandpa: grandpa::{Module, Call, Storage, Event, Config},
ImOnline: im_online::{default, ValidateUnsigned},
FinalityTracker: finality_tracker::{Module, Call, Inherent},
Offences: offences::{Module, Call, Storage, Event},
Session: session::{Module, Call, Storage, Event, Config<T>},
Expand All @@ -451,7 +451,7 @@ construct_runtime!(
Utility: utility::{Module, Call, Event},

EthRelay: eth_relay::{Module, Call, Storage, Event<T>, Config},
EthBacking: eth_backing::{Module, Call, Storage, Event<T>, Config<T>},
EthBacking: eth_backing,
}
);

Expand Down
22 changes: 10 additions & 12 deletions srml/eth-backing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,42 @@ edition = "2018"

[dependencies]
# crates.io
serde = { version = "1.0.101", optional = true }
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] }
hex = { version = "0.4", default-features = false }
serde = { version = "1.0.101", optional = true }

# github.com
rstd = { package = "sr-std", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }
support = { package = "srml-support", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }
system = { package = "srml-system", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }
timestamp = { package = "srml-timestamp", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }
sr-primitives = { git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }
primitives = { package = "substrate-primitives", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }
ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "with_no_std", default-features = false }

# darwinia
darwinia-support = { package = "darwinia-support", path = "../support", default-features = false }
darwinia-eth-relay = { package = "darwinia-eth-relay", path = "../eth-relay", default-features = false }
sr-eth-primitives = { path = "../../core/sr-eth-primitives", default-features = false }

sr-primitives = { git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }

primitives = { package = "substrate-primitives", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop", default-features = false }

ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "with_no_std", default-features = false }

hex = { version = "0.4", default-features = false}

[dev-dependencies]
hex-literal = "0.2.1"

[features]
default = ["std"]
std = [
"codec/std",
"hex/std",
"serde/std",
"hex/std",

"ethabi/std",
"rstd/std",
"sr-primitives/std",
"support/std",
"system/std",
"timestamp/std",

"darwinia-support/std",
"darwinia-eth-relay/std",
"sr-eth-primitives/std",
"ethabi/std",
"sr-primitives/std",
]
193 changes: 98 additions & 95 deletions srml/eth-backing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,24 @@
#![cfg_attr(not(feature = "std"), no_std)]

//use codec::{Decode, Encode};
use rstd::{borrow::ToOwned, result};
use rstd::{marker::PhantomData, prelude::*}; // fmt::Debug,
use ethabi::{Event as EthEvent, EventParam as EthEventParam, ParamType, RawLog};
use rstd::{borrow::ToOwned, convert::TryFrom, marker::PhantomData, result, vec, vec::Vec}; // fmt::Debug
use sr_primitives::traits::{SaturatedConversion, Saturating};
use support::{decl_event, decl_module, decl_storage, ensure, traits::Currency, traits::OnUnbalanced}; // dispatch::Result,
use system::ensure_signed;

use sr_primitives::traits::{SaturatedConversion, Saturating}; // Convert,
use system::ensure_signed; // Convert,

//use sr_primitives::RuntimeDebug;
//use primitives::crypto::UncheckedFrom;
//use core::convert::TryFrom;

use darwinia_eth_relay::{EthReceiptProof, VerifyEthReceipts};
use darwinia_support::{LockableCurrency, OnDepositRedeem};
use ethabi::{Event as EthEvent, EventParam as EthEventParam, ParamType, RawLog};
use sr_eth_primitives::{EthAddress, H256, U256}; // receipt::LogEntry, receipt::Receipt,

//#[cfg(feature = "std")]
//use sr_primitives::{Deserialize, Serialize};

use rstd::vec::Vec;

pub type Balance = u128;
pub type Moment = u64;

type RingBalanceOf<T> = <<T as Trait>::Ring as Currency<<T as system::Trait>::AccountId>>::Balance;
Expand Down Expand Up @@ -89,109 +86,42 @@ decl_module! {
pub fn redeem_ring(origin, proof_record: EthReceiptProof) {
let _relayer = ensure_signed(origin)?;

ensure!(!<RingProofVerified>::exists((proof_record.header_hash, proof_record.index)), "Ring for this proof has already been redeemed.");

let verified_receipt = T::EthRelay::verify_receipt(&proof_record)?;

// event RingBurndropTokens(address indexed token, address indexed owner, uint amount, bytes data);
// https://ropsten.etherscan.io/tx/0x81f699c93b00ab0b7db701f87b6f6045c1e0692862fcaaf8f06755abb0536800
let eth_event = EthEvent {
name: "RingBurndropTokens".to_owned(),
inputs: vec![
EthEventParam {name: "token".to_owned(), kind: ParamType::Address, indexed: true,},
EthEventParam {name: "owner".to_owned(), kind: ParamType::Address, indexed: true,},
EthEventParam {name: "amount".to_owned(), kind: ParamType::Uint(256), indexed: false,},
EthEventParam {name: "data".to_owned(), kind: ParamType::Bytes, indexed: false,}
],
anonymous: false,
};

// H256::from(hex!("38045eaef0a21b74ff176350f18df02d9041a25d6694b5f63e9474b7b6cd6b94")
let log_entry = verified_receipt.logs.iter().find(
|&x| x.address == Self::ring_redeem_address()
&& x.topics[0] == eth_event.signature()
).expect("Log Entry Not Found");

let log = RawLog {
topics: [log_entry.topics[0],log_entry.topics[1],log_entry.topics[2]].to_vec(),
data: log_entry.data.clone()
};

let result = eth_event.parse_log(log).expect("Parse Eth Log Error");

// TODO: div 10**18 and mul 10**9
let mut amount : U256 = result.params[2].value.clone().to_uint().expect("Param Convert to Int Failed.");
amount = amount / U256::from(1_000_000_000u64);

let raw_sub_key : Vec<u8> = result.params[3].value.clone().to_bytes().expect("Param Convert to Bytes Failed.");
ensure!(
!RingProofVerified::exists((proof_record.header_hash, proof_record.index)),
"Ring For This Proof - ALREADY BEEN REDEEMED",
);

let decoded_sub_key = hex::decode(&raw_sub_key[..]).expect("Address Hex decode Failed.");
let darwinia_account = T::DetermineAccountId::account_id_for(&decoded_sub_key[..])?;
let (darwinia_account, redeemed_amount) = Self::parse_proof(&proof_record, "RingBurndropTokens")?;
let redeemed_ring = <RingBalanceOf<T>>::saturated_from(redeemed_amount);
let redeemed_positive_imbalance_ring = T::Ring::deposit_into_existing(&darwinia_account, redeemed_ring)?;

let redeemed_amount = amount.as_u128().saturated_into();
T::RingReward::on_unbalanced(redeemed_positive_imbalance_ring);

RingProofVerified::insert((proof_record.header_hash, proof_record.index), proof_record);
<RingLocked<T>>::mutate(|l| {
*l = l.saturating_sub(redeemed_amount);
*l = l.saturating_sub(redeemed_ring);
});

<RingProofVerified>::insert((proof_record.header_hash, proof_record.index), proof_record);

let redeemed_ring = T::Ring::deposit_into_existing(&darwinia_account, redeemed_amount).expect("Deposit into existing failed.");

T::RingReward::on_unbalanced(redeemed_ring);
}

// event KtonBurndropTokens(address indexed token, address indexed owner, uint amount, bytes data);
pub fn redeem_kton(origin, proof_record: EthReceiptProof) {
let _relayer = ensure_signed(origin)?;

ensure!(!<KtonProofVerified>::exists((proof_record.header_hash, proof_record.index)), "Kton for this proof has already been redeemed.");
ensure!(
!KtonProofVerified::exists((proof_record.header_hash, proof_record.index)),
"Kton For This Proof - ALREADY BEEN REDEEMED",
);

let verified_receipt = T::EthRelay::verify_receipt(&proof_record)?;
let (darwinia_account, redeemed_amount) = Self::parse_proof(&proof_record, "KtonBurndropTokens")?;
let redeemed_kton = <KtonBalanceOf<T>>::saturated_from(redeemed_amount);
let redeemed_positive_imbalance_kton = T::Kton::deposit_into_existing(&darwinia_account, redeemed_kton)?;

// event RingBurndropTokens(address indexed token, address indexed owner, uint amount, bytes data);
// https://ropsten.etherscan.io/tx/0x81f699c93b00ab0b7db701f87b6f6045c1e0692862fcaaf8f06755abb0536800
let eth_event = EthEvent {
name: "KtonBurndropTokens".to_owned(),
inputs: vec![
EthEventParam {name: "token".to_owned(), kind: ParamType::Address, indexed: true,},
EthEventParam {name: "owner".to_owned(), kind: ParamType::Address, indexed: true,},
EthEventParam {name: "amount".to_owned(), kind: ParamType::Uint(256), indexed: false,},
EthEventParam {name: "data".to_owned(), kind: ParamType::Bytes, indexed: false,}
],
anonymous: false,
};

let log_entry = verified_receipt.logs.iter().find(
|&x| x.address == Self::kton_redeem_address()
&& x.topics[0] == eth_event.signature()
).expect("Log Entry Not Found");

let log = RawLog {
topics: [log_entry.topics[0],log_entry.topics[1],log_entry.topics[2]].to_vec(),
data: log_entry.data.clone()
};

let result = eth_event.parse_log(log).expect("Parse Eth Log Error");
// TODO: div 10**18 and mul 10**9
let mut amount : U256 = result.params[2].value.clone().to_uint().expect("Param Convert to Int Failed.");
amount = amount / U256::from(1_000_000_000u64);
let raw_sub_key : Vec<u8> = result.params[3].value.clone().to_bytes().expect("Param Convert to Bytes Failed.");

let decoded_sub_key = hex::decode(&raw_sub_key[..]).expect("Address Hex decode Failed.");
let darwinia_account = T::DetermineAccountId::account_id_for(&decoded_sub_key[..])?;

let redeemed_amount = amount.as_u128().saturated_into();
T::KtonReward::on_unbalanced(redeemed_positive_imbalance_kton);

KtonProofVerified::insert((proof_record.header_hash, proof_record.index), proof_record);
<KtonLocked<T>>::mutate(|l| {
*l = l.saturating_sub(redeemed_amount);
*l = l.saturating_sub(redeemed_kton);
});

<KtonProofVerified>::insert((proof_record.header_hash, proof_record.index), proof_record);

let redeemed_kton = T::Kton::deposit_into_existing(&darwinia_account, redeemed_amount).expect("Deposit into existing failed.");

T::KtonReward::on_unbalanced(redeemed_kton);
}

// https://github.com/evolutionlandorg/bank
Expand Down Expand Up @@ -266,6 +196,79 @@ decl_module! {
}
}

impl<T: Trait> Module<T> {
fn parse_proof(proof: &EthReceiptProof, event_name: &str) -> result::Result<(T::AccountId, Balance), &'static str> {
aurexav marked this conversation as resolved.
Show resolved Hide resolved
let verified_receipt = T::EthRelay::verify_receipt(proof)?;

// event RingBurndropTokens(address indexed token, address indexed owner, uint amount, bytes data);
// https://ropsten.etherscan.io/tx/0x81f699c93b00ab0b7db701f87b6f6045c1e0692862fcaaf8f06755abb0536800
// event KtonBurndropTokens(address indexed token, address indexed owner, uint amount, bytes data);
// TODO: address
let result = {
let eth_event = EthEvent {
name: event_name.to_owned(),
inputs: vec![
EthEventParam {
name: "token".to_owned(),
kind: ParamType::Address,
indexed: true,
},
EthEventParam {
name: "owner".to_owned(),
kind: ParamType::Address,
indexed: true,
},
EthEventParam {
name: "amount".to_owned(),
kind: ParamType::Uint(256),
indexed: false,
},
EthEventParam {
name: "data".to_owned(),
kind: ParamType::Bytes,
indexed: false,
},
],
anonymous: false,
};
let log_entry = verified_receipt
.logs
.into_iter()
.find(|x| x.address == Self::ring_redeem_address() && x.topics[0] == eth_event.signature())
.ok_or("Log Entry - NOT FOUND")?;
let log = RawLog {
topics: vec![log_entry.topics[0], log_entry.topics[1], log_entry.topics[2]],
data: log_entry.data.clone(),
};

eth_event.parse_log(log).map_err(|_| "Parse Eth Log - FAILED")?
};
let redeemed_amount = {
// TODO: div 10**18 and mul 10**9
let amount = result.params[2]
.value
.clone()
.to_uint()
.map(|x| x / U256::from(1_000_000_000u64))
.ok_or("Convert to Int - FAILED")?;

Balance::try_from(amount)?
};
let darwinia_account = {
let raw_sub_key = result.params[3]
.value
.clone()
.to_bytes()
.ok_or("Convert to Bytes - FAILED")?;
let decoded_sub_key = hex::decode(&raw_sub_key).map_err(|_| "Decode Address - FAILED")?;

T::DetermineAccountId::account_id_for(&decoded_sub_key)?
};

Ok((darwinia_account, redeemed_amount))
}
}

pub trait AccountIdFor<AccountId> {
// fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId;
fn account_id_for(decoded_sub_key: &[u8]) -> result::Result<AccountId, &'static str>;
Expand Down