Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
bdd94b4
Rename Palette to FRAME (#4182)
shawntabrizi Nov 22, 2019
8714bb7
The crate rename (#4223)
gnunicorn Dec 2, 2019
9606294
pallet-evm: weight calculation for call/create based on gas provided …
sorpaas Dec 3, 2019
203ad75
Rename folder: primitives/sr-primitives -> primitives/runtime (#4280)
kigawas Dec 9, 2019
594899f
Rename: primitives/sr-std -> primitives/sp-std (#4327)
kigawas Dec 10, 2019
1676ff1
Fix warnings when compiling runtime. (#4332)
tomusdrw Dec 10, 2019
943c38a
Rename: primitives/sr-io -> primitives/sp-io (#4328)
kigawas Dec 10, 2019
27662d7
[big refactor] Remove crate aliasing. (#4395)
tomusdrw Dec 16, 2019
911ad26
Setting versions locally towards 2.0 release (#4404)
gnunicorn Dec 17, 2019
884b92a
More `decl_error!` migrations (#4427)
shawntabrizi Dec 18, 2019
9db339d
pallet-evm: default implementation for FeeCalculator and ConvertAccou…
sorpaas Dec 18, 2019
310dd66
Make `decl_error!` errors usable (#4449)
bkchr Dec 19, 2019
8ddd230
Update copyright year (#4532)
shawntabrizi Jan 5, 2020
3195f11
Modify doublemap syntax (#4576)
gui1117 Jan 10, 2020
b41f89b
Improve PaysFee trait and dispatch info logic in utility module (#4606)
xlc Jan 13, 2020
af1f5f0
Remove default hasher (#4739)
gui1117 Jan 27, 2020
9ad76c3
clarify licensing (#4755)
gnunicorn Jan 29, 2020
b88b377
pallet-evm: log created address (#4821)
sorpaas Feb 4, 2020
4c27f40
update primitive types to 0.6.2 (#4866)
NikVolf Feb 10, 2020
a3a3402
pallet-evm: optional nonce parameter (#4893)
sorpaas Feb 11, 2020
442b9bd
pallet-evm: add support for transaction-level create2 (#4907)
sorpaas Feb 13, 2020
fb73f4f
pallet-evm: refactor duplicate code in call/create/create2 (#4922)
sorpaas Feb 13, 2020
0d47116
Fix various spelling errors (#4940)
shawntabrizi Feb 17, 2020
2774b13
Cargo.toml fixups for the release (#4975)
gnunicorn Feb 21, 2020
d1c6b17
prepare version to alpha.1 (#5055)
gnunicorn Feb 25, 2020
3beb4a8
set missing metadata fields, prepping alpha.2 (#5067)
gnunicorn Feb 26, 2020
565e2bd
prepping for Alpha.3 (#5080)
gnunicorn Feb 27, 2020
f547546
Update to SCALE 1.2.0 (#5113)
bkchr Mar 3, 2020
b65b739
Assign unique storage names to pallets. (#5010)
shawntabrizi Mar 14, 2020
576fa05
Refactor away from opaque hashes (#5226)
gavofyork Mar 16, 2020
0db4eaf
Releasing 2.0.0-alpha.4 (#5279)
gnunicorn Mar 18, 2020
4ad91db
Update dependencies (#5316)
gnunicorn Mar 19, 2020
a7b9e57
pallet-evm: configurable gasometer config (#5320)
sorpaas Mar 23, 2020
1823db7
Releasing 2.0.0-alpha.5 (#5340)
gnunicorn Mar 24, 2020
7c10c40
Upgrade `parity-scale-codec` to `1.3.0` (#5443)
bkchr Mar 28, 2020
86a200d
Build for only one target for docs.rs (#5427)
pscott Mar 30, 2020
c996f09
Add deposit/withdraw events to EVM module (#5440)
drewstone Mar 31, 2020
0bf5600
Prepping release of alpha.6 (#5629)
gnunicorn Apr 14, 2020
c881267
Switch pre-release version to dev (#5637)
gnunicorn Apr 15, 2020
3b3effe
Weights to u64 + Balances Weights (#5446)
shawntabrizi Apr 16, 2020
3f64bd4
Migrate away from `SimpleDispatchInfo` (#5686)
kianenigma Apr 22, 2020
b9585bb
enum Pays for PaysFee (#5733)
kianenigma Apr 22, 2020
b53850e
Make Pallet ModuleId and LockIdentifier Configurable (#5695)
emostov Apr 24, 2020
d813bb7
Introduce `BlockExecutionWeight` and `ExtrinsicBaseWeight` (#5722)
shawntabrizi Apr 25, 2020
9812637
Release of Alpha.7 (#5904)
gnunicorn May 5, 2020
9170338
post release dev reset (#5911)
gnunicorn May 5, 2020
0faf212
Relax substrate licensing scheme (#5947)
gnunicorn May 15, 2020
7572547
Releasing Alpha.8 (#6048)
gnunicorn May 15, 2020
6fd2c4d
resetting to -dev (#6050)
gnunicorn May 16, 2020
80cf326
Refactor EVM operations to module functions (#6056)
sorpaas May 18, 2020
2e40259
evm: allow setting pre-defined accounts in genesis (#6086)
sorpaas May 20, 2020
adad2f2
Tagging as rc1
gnunicorn May 25, 2020
fdc89b8
Releasing rc2 (#6136)
gnunicorn May 26, 2020
2ebd4a9
pallet-evm ensure gas_price + Storage getter (#6191)
tgmichel Jun 2, 2020
e38eaa7
Intent to release rc3 (#6290)
gnunicorn Jun 8, 2020
fba1d8f
Deprecate FunctionOf and remove its users (#6340)
athei Jun 12, 2020
ad2e66e
pallet-evm add get(fn) to AccountStorages (#6279)
tgmichel Jun 15, 2020
dbebed1
Validate encoding of extrinsics passed to runtime (#6442)
arkpar Jun 19, 2020
9d3f32d
Releasing rc4 – Rhinoceros (#6515)
gnunicorn Jun 25, 2020
58fab4b
pallet-evm: customizable chain id (#6537)
sorpaas Jul 1, 2020
e6444fc
pallet-evm: return Ok(()) when EVM execution fails (#6493)
sorpaas Jul 4, 2020
add655d
decl_module! macro: use 'frame_system' instead of `system` as default…
shaunxw Jul 7, 2020
54faded
Add `WeightInfo` to all pallets with benchmarks. (#6575)
shawntabrizi Jul 8, 2020
a6c2743
Make evm errors public (#6598)
crystalin Jul 9, 2020
6b74723
Remove duplicate comments (#6638)
kianenigma Jul 12, 2020
99bb8a4
Implement apply_state flag and allow fetching return data and used g…
sorpaas Jul 14, 2020
0c68ba4
identity: Don't let subs be re-registered (#6667)
gavofyork Jul 17, 2020
cdf0064
More app-friendly event description (#6684)
warfollowsme Jul 20, 2020
e810e91
Fixup `cargo unleash` (#6689)
gnunicorn Jul 21, 2020
d728058
Support using system storage directly for EVM balance and nonce (#6659)
sorpaas Jul 23, 2020
733830c
pallet-evm: add support for tuple-based precompile declarations (#6681)
sorpaas Jul 27, 2020
9d11944
Update parity-scale-codec to prepare for breaking rustc release (#6746)
bkchr Jul 28, 2020
5947d43
pallet-evm: add builtin support for the four basic Ethereum precompil…
sorpaas Jul 30, 2020
8128077
pallet-evm: move gas price check to execute_evm (#6837)
sorpaas Aug 8, 2020
6e83aaf
pallet-evm: fix wrong logic in mutate_account_basic (#6786)
sorpaas Aug 12, 2020
bdcacd2
pallet-evm: avoid double fee payment (#6858)
sorpaas Aug 13, 2020
9da3684
Adds debug logs to EVM frame (#6887)
crystalin Aug 14, 2020
9474646
prepping for releasing rc6 (#6922)
gnunicorn Aug 20, 2020
bbbd296
fix pallet-evm features (#6995)
xlc Sep 1, 2020
81c0265
Improves EVM gas price check (#7051)
crystalin Sep 8, 2020
33e778e
Fail docs on warnings (#5923)
TriplEight Sep 11, 2020
ac19d1d
WeightInfo for Vesting Pallet (#7103)
shawntabrizi Sep 16, 2020
fe58e35
evm: Add executor logs to execute_evm response (#7048)
tgmichel Sep 21, 2020
bbcb3ee
Update READMEs, fix links (#7176)
stiiifff Sep 22, 2020
ea6558e
Rename `ModuleToIndex` to `PalletRuntimeSetup` (#7148)
bkchr Sep 22, 2020
66da36b
Releasing 2.0 – two dot 😮 (#7182)
gnunicorn Sep 22, 2020
b026ab4
pallet-evm: fix backend timestamp (#7245)
sorpaas Sep 30, 2020
c14ebd5
Fixes evm ripemd160 impl to use 32 bytes (#7296)
crystalin Oct 9, 2020
5912d5d
Write pallet_evm README (#7487)
ashWhiteHat Nov 8, 2020
1ca6f74
Add 'frame/evm/' from commit '5912d5d51349caad5d13da0ff2cd8784cc5be21f'
sorpaas Nov 20, 2020
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
51 changes: 51 additions & 0 deletions frame/evm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[package]
name = "pallet-evm"
version = "2.0.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME EVM contracts pallet"
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
serde = { version = "1.0.101", optional = true, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false }
frame-support = { version = "2.0.0", default-features = false, path = "../support" }
frame-system = { version = "2.0.0", default-features = false, path = "../system" }
pallet-timestamp = { version = "2.0.0", default-features = false, path = "../timestamp" }
pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" }
sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" }
sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" }
sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" }
primitive-types = { version = "0.7.0", default-features = false, features = ["rlp", "byteorder"] }
rlp = { version = "0.4", default-features = false }
evm = { version = "0.17", default-features = false }
sha3 = { version = "0.8", default-features = false }
impl-trait-for-tuples = "0.1"
ripemd160 = { version = "0.9", default-features = false }

[features]
default = ["std"]
std = [
"serde",
"codec/std",
"sp-core/std",
"sp-runtime/std",
"frame-support/std",
"frame-system/std",
"pallet-balances/std",
"sp-io/std",
"sp-std/std",
"sha3/std",
"rlp/std",
"primitive-types/std",
"evm/std",
"pallet-timestamp/std",
"ripemd160/std",
]
29 changes: 29 additions & 0 deletions frame/evm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# EVM Module

The EVM module allows unmodified EVM code to be executed in a Substrate-based blockchain.
- [`evm::Trait`](https://docs.rs/pallet-evm/2.0.0/pallet_evm/trait.Trait.html)

## EVM Engine

The EVM module uses [`SputnikVM`](https://github.com/rust-blockchain/evm) as the underlying EVM engine. The engine is overhauled so that it's [`modular`](https://github.com/corepaper/evm).

## Execution Lifecycle

There are a separate set of accounts managed by the EVM module. Substrate based accounts can call the EVM Module to deposit or withdraw balance from the Substrate base-currency into a different balance managed and used by the EVM module. Once a user has populated their balance, they can create and call smart contracts using this module.

There's one-to-one mapping from Substrate accounts and EVM external accounts that is defined by a conversion function.

## EVM Module vs Ethereum Network

The EVM module should be able to produce nearly identical results compared to the Ethereum mainnet, including gas cost and balance changes.

Observable differences include:

- The available length of block hashes may not be 256 depending on the configuration of the System module in the Substrate runtime.
- Difficulty and coinbase, which do not make sense in this module and is currently hard coded to zero.

We currently do not aim to make unobservable behaviors, such as state root, to be the same. We also don't aim to follow the exact same transaction / receipt format. However, given one Ethereum transaction and one Substrate account's private key, one should be able to convert any Ethereum transaction into a transaction compatible with this module.

The gas configurations are configurable. Right now, a pre-defined Istanbul hard fork configuration option is provided.

License: Apache-2.0
216 changes: 216 additions & 0 deletions frame/evm/src/backend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
use sp_std::marker::PhantomData;
use sp_std::vec::Vec;
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use codec::{Encode, Decode};
use sp_core::{U256, H256, H160};
use sp_runtime::traits::UniqueSaturatedInto;
use frame_support::traits::Get;
use frame_support::{debug, storage::{StorageMap, StorageDoubleMap}};
use sha3::{Keccak256, Digest};
use evm::backend::{Backend as BackendT, ApplyBackend, Apply};
use crate::{Trait, AccountStorages, AccountCodes, Module, Event};

#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
/// Ethereum account nonce, balance and code. Used by storage.
pub struct Account {
/// Account nonce.
pub nonce: U256,
/// Account balance.
pub balance: U256,
}

#[derive(Clone, Eq, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
/// Ethereum log. Used for `deposit_event`.
pub struct Log {
/// Source address of the log.
pub address: H160,
/// Topics of the log.
pub topics: Vec<H256>,
/// Byte array data of the log.
pub data: Vec<u8>,
}

#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
/// External input from the transaction.
pub struct Vicinity {
/// Current transaction gas price.
pub gas_price: U256,
/// Origin of the transaction.
pub origin: H160,
}

/// Substrate backend for EVM.
pub struct Backend<'vicinity, T> {
vicinity: &'vicinity Vicinity,
_marker: PhantomData<T>,
}

impl<'vicinity, T> Backend<'vicinity, T> {
/// Create a new backend with given vicinity.
pub fn new(vicinity: &'vicinity Vicinity) -> Self {
Self { vicinity, _marker: PhantomData }
}
}

impl<'vicinity, T: Trait> BackendT for Backend<'vicinity, T> {
fn gas_price(&self) -> U256 { self.vicinity.gas_price }
fn origin(&self) -> H160 { self.vicinity.origin }

fn block_hash(&self, number: U256) -> H256 {
if number > U256::from(u32::max_value()) {
H256::default()
} else {
let number = T::BlockNumber::from(number.as_u32());
H256::from_slice(frame_system::Module::<T>::block_hash(number).as_ref())
}
}

fn block_number(&self) -> U256 {
let number: u128 = frame_system::Module::<T>::block_number().unique_saturated_into();
U256::from(number)
}

fn block_coinbase(&self) -> H160 {
H160::default()
}

fn block_timestamp(&self) -> U256 {
let now: u128 = pallet_timestamp::Module::<T>::get().unique_saturated_into();
U256::from(now / 1000)
}

fn block_difficulty(&self) -> U256 {
U256::zero()
}

fn block_gas_limit(&self) -> U256 {
U256::zero()
}

fn chain_id(&self) -> U256 {
U256::from(T::ChainId::get())
}

fn exists(&self, _address: H160) -> bool {
true
}

fn basic(&self, address: H160) -> evm::backend::Basic {
let account = Module::<T>::account_basic(&address);

evm::backend::Basic {
balance: account.balance,
nonce: account.nonce,
}
}

fn code_size(&self, address: H160) -> usize {
AccountCodes::decode_len(&address).unwrap_or(0)
}

fn code_hash(&self, address: H160) -> H256 {
H256::from_slice(Keccak256::digest(&AccountCodes::get(&address)).as_slice())
}

fn code(&self, address: H160) -> Vec<u8> {
AccountCodes::get(&address)
}

fn storage(&self, address: H160, index: H256) -> H256 {
AccountStorages::get(address, index)
}
}

impl<'vicinity, T: Trait> ApplyBackend for Backend<'vicinity, T> {
fn apply<A, I, L>(
&mut self,
values: A,
logs: L,
delete_empty: bool,
) where
A: IntoIterator<Item=Apply<I>>,
I: IntoIterator<Item=(H256, H256)>,
L: IntoIterator<Item=evm::backend::Log>,
{
for apply in values {
match apply {
Apply::Modify {
address, basic, code, storage, reset_storage,
} => {
Module::<T>::mutate_account_basic(&address, Account {
nonce: basic.nonce,
balance: basic.balance,
});

if let Some(code) = code {
debug::debug!(
target: "evm",
"Inserting code ({} bytes) at {:?}",
code.len(),
address
);
AccountCodes::insert(address, code);
}

if reset_storage {
AccountStorages::remove_prefix(address);
}

for (index, value) in storage {
if value == H256::default() {
debug::debug!(
target: "evm",
"Removing storage for {:?} [index: {:?}]",
address,
index
);
AccountStorages::remove(address, index);
} else {
debug::debug!(
target: "evm",
"Updating storage for {:?} [index: {:?}, value: {:?}]",
address,
index,
value
);
AccountStorages::insert(address, index, value);
}
}

if delete_empty {
Module::<T>::remove_account_if_empty(&address);
}
},
Apply::Delete { address } => {
debug::debug!(
target: "evm",
"Deleting account at {:?}",
address
);
Module::<T>::remove_account(&address)
},
}
}

for log in logs {
debug::trace!(
target: "evm",
"Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]",
log.address,
log.topics.len(),
log.topics,
log.data.len(),
log.data
);
Module::<T>::deposit_event(Event::<T>::Log(Log {
address: log.address,
topics: log.topics,
data: log.data,
}));
}
}
}
Loading