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

Allow whitleisting contract deployer #1629

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ derive_more = "1.0"
environmental = { version = "1.1.4", default-features = false }
ethereum = { git = "https://github.com/rust-ethereum/ethereum", rev = "3be0d8fd4c2ad1ba216b69ef65b9382612efc8ba", default-features = false }
ethereum-types = { version = "0.15", default-features = false }
evm = { git = "https://github.com/rust-ethereum/evm", branch = "v0.x", default-features = false }
evm = { git = "https://github.com/girazoki/evm", branch = "girazoki-bring-changes-set-code", default-features = false }
futures = "0.3.31"
hash-db = { version = "0.16.0", default-features = false }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
Expand Down
8 changes: 7 additions & 1 deletion frame/ethereum/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

//! Test utilities

use core::str::FromStr;
use ethereum::{TransactionAction, TransactionSignature};
use rlp::RlpStream;
// Substrate
Expand All @@ -27,7 +28,7 @@ use sp_runtime::{
AccountId32, BuildStorage,
};
// Frontier
use pallet_evm::{config_preludes::ChainId, AddressMapping};
use pallet_evm::{config_preludes::ChainId, AddressMapping, EnsureAllowedCreateAddress};

use super::*;

Expand Down Expand Up @@ -86,12 +87,17 @@ impl FindAuthor<H160> for FindAuthorTruncated {
parameter_types! {
pub const TransactionByteFee: u64 = 1;
pub const GasLimitStorageGrowthRatio: u64 = 0;
// Alice is allowed to create contracts via CREATE and CALL(CREATE)
pub AllowedAddressesCreate: Vec<H160> = vec![H160::from_str("0x1a642f0e3c3af545e7acbd38b07251b3990914f1").expect("alice address")];
pub AllowedAddressesCreateInner: Vec<H160> = vec![H160::from_str("0x1a642f0e3c3af545e7acbd38b07251b3990914f1").expect("alice address")];
}

#[derive_impl(pallet_evm::config_preludes::TestDefaultConfig)]
impl pallet_evm::Config for Test {
type AccountProvider = pallet_evm::FrameSystemAccountProvider<Self>;
type BlockHashMapping = crate::EthereumBlockHashMapping<Self>;
type CreateOriginFilter = EnsureAllowedCreateAddress<AllowedAddressesCreate>;
type CreateInnerOriginFilter = EnsureAllowedCreateAddress<AllowedAddressesCreateInner>;
type Currency = Balances;
type PrecompilesType = ();
type PrecompilesValue = ();
Expand Down
150 changes: 149 additions & 1 deletion frame/ethereum/src/tests/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ use super::*;
use evm::{ExitReason, ExitRevert, ExitSucceed};
use fp_ethereum::{TransactionData, ValidatedTransaction};
use frame_support::{
dispatch::{DispatchClass, GetDispatchInfo},
dispatch::{DispatchClass, GetDispatchInfo, Pays, PostDispatchInfo},
weights::Weight,
};
use pallet_evm::AddressMapping;
use sp_runtime::{DispatchError, DispatchErrorWithPostInfo, ModuleError};

fn legacy_erc20_creation_unsigned_transaction() -> LegacyUnsignedTransaction {
LegacyUnsignedTransaction {
Expand All @@ -41,6 +42,21 @@ fn legacy_erc20_creation_transaction(account: &AccountInfo) -> Transaction {
legacy_erc20_creation_unsigned_transaction().sign(&account.private_key)
}

fn legacy_foo_bar_contract_creation_unsigned_transaction() -> LegacyUnsignedTransaction {
LegacyUnsignedTransaction {
nonce: U256::zero(),
gas_price: U256::from(1),
gas_limit: U256::from(0x100000),
action: ethereum::TransactionAction::Create,
value: U256::zero(),
input: hex::decode(FOO_BAR_CONTRACT_CREATOR_BYTECODE.trim_end()).unwrap(),
}
}

fn legacy_foo_bar_contract_creation_transaction(account: &AccountInfo) -> Transaction {
legacy_foo_bar_contract_creation_unsigned_transaction().sign(&account.private_key)
}

#[test]
fn transaction_should_increment_nonce() {
let (pairs, mut ext) = new_test_ext(1);
Expand Down Expand Up @@ -273,6 +289,138 @@ fn transaction_should_generate_correct_gas_used() {
});
}

#[test]
fn contract_creation_succeeds_with_allowed_address() {
let (pairs, mut ext) = new_test_ext(1);
let alice = &pairs[0];

ext.execute_with(|| {
// Alice can deploy contracts
let t = LegacyUnsignedTransaction {
nonce: U256::zero(),
gas_price: U256::from(1),
gas_limit: U256::from(0x100000),
action: ethereum::TransactionAction::Create,
value: U256::zero(),
input: hex::decode(TEST_CONTRACT_CODE).unwrap(),
}
.sign(&alice.private_key);
assert_ok!(Ethereum::execute(alice.address, &t, None,));
});
}

#[test]
fn contract_creation_fails_with_not_allowed_address() {
let (pairs, mut ext) = new_test_ext(2);
let bob = &pairs[1];

ext.execute_with(|| {
// Bob can't deploy contracts
let t = LegacyUnsignedTransaction {
nonce: U256::zero(),
gas_price: U256::from(1),
gas_limit: U256::from(0x100000),
action: ethereum::TransactionAction::Create,
value: U256::zero(),
input: hex::decode(TEST_CONTRACT_CODE).unwrap(),
}
.sign(&bob.private_key);

let result = Ethereum::execute(bob.address, &t, None);
assert!(result.is_err());

// Note: assert_err! macro doesn't work here because we receive 'None' as
// 'actual_weight' using assert_err instead of Some(Weight::default()),
// but the error is the same "CreateOriginNotAllowed".
assert_eq!(
result,
Err(DispatchErrorWithPostInfo {
post_info: PostDispatchInfo {
actual_weight: Some(Weight::default()),
pays_fee: Pays::Yes
},
error: DispatchError::Module(ModuleError {
index: 3,
error: [13, 0, 0, 0],
message: Some("CreateOriginNotAllowed")
})
})
);
});
}

#[test]
fn inner_contract_creation_succeeds_with_allowed_address() {
let (pairs, mut ext) = new_test_ext(1);
let alice = &pairs[0];

ext.execute_with(|| {
let t = legacy_foo_bar_contract_creation_transaction(alice);
assert_ok!(Ethereum::execute(alice.address, &t, None,));

let contract_address = hex::decode("32dcab0ef3fb2de2fce1d2e0799d36239671f04a").unwrap();
let new_bar = hex::decode("2fc11060").unwrap();

// Alice is allowed to deploy contracts via inner calls.
let new_bar_inner_creation_tx = LegacyUnsignedTransaction {
nonce: U256::from(1),
gas_price: U256::from(1),
gas_limit: U256::from(0x100000),
action: TransactionAction::Call(H160::from_slice(&contract_address)),
value: U256::zero(),
input: new_bar,
}
.sign(&alice.private_key);

let (_, _, info) =
Ethereum::execute(alice.address, &new_bar_inner_creation_tx, None).unwrap();

assert!(Ethereum::execute(alice.address, &new_bar_inner_creation_tx, None).is_ok());
match info {
CallOrCreateInfo::Call(info) => {
assert_eq!(info.exit_reason, ExitReason::Succeed(ExitSucceed::Returned));
}
CallOrCreateInfo::Create(_) => panic!("expected call info"),
}
});
}

#[test]
fn inner_contract_creation_reverts_with_not_allowed_address() {
let (pairs, mut ext) = new_test_ext(2);
let alice = &pairs[0];
let bob = &pairs[1];

ext.execute_with(|| {
let t = legacy_foo_bar_contract_creation_transaction(alice);
assert_ok!(Ethereum::execute(alice.address, &t, None,));

let contract_address = hex::decode("32dcab0ef3fb2de2fce1d2e0799d36239671f04a").unwrap();
let new_bar = hex::decode("2fc11060").unwrap();

// Bob is not allowed to deploy contracts via inner calls.
let new_bar_inner_creation_tx = LegacyUnsignedTransaction {
nonce: U256::from(1),
gas_price: U256::from(1),
gas_limit: U256::from(0x100000),
action: TransactionAction::Call(H160::from_slice(&contract_address)),
value: U256::zero(),
input: new_bar,
}
.sign(&bob.private_key);

let (_, _, info) =
Ethereum::execute(bob.address, &new_bar_inner_creation_tx, None).unwrap();

match info {
CallOrCreateInfo::Call(info) => {
assert_eq!(info.exit_reason, ExitReason::Revert(ExitRevert::Reverted));
}
CallOrCreateInfo::Create(_) => panic!("expected call info"),
}
});
}

#[test]
fn call_should_handle_errors() {
let (pairs, mut ext) = new_test_ext(1);
Expand Down
23 changes: 23 additions & 0 deletions frame/ethereum/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,26 @@ pub const ERC20_CONTRACT_BYTECODE: &str = include_str!("./res/erc20_contract_byt
// }
// }
pub const TEST_CONTRACT_CODE: &str = "608060405234801561001057600080fd5b50610129806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c8063c2985578146037578063febb0f7e146055575b600080fd5b603d605d565b60405180821515815260200191505060405180910390f35b605b6066565b005b60006001905090565b600060bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001806100bf6035913960400191505060405180910390fd5b56fe766572795f6c6f6e675f6572726f725f6d73675f746861745f77655f6578706563745f746f5f62655f7472696d6d65645f61776179a26469706673582212207af96dd688d3a3adc999c619e6073d5b6056c72c79ace04a90ea4835a77d179364736f6c634300060c0033";

// pragma solidity ^0.8.2;
// contract Foo {
// function newBar() // 2fc11060
// public
// returns(Bar newContract)
// {
// Bar b = new Bar();
// return b;
// }
//}

// contract Bar {
// function getNumber()
// public
// pure
// returns (uint32 number)
// {
// return 10;
// }
//}
pub const FOO_BAR_CONTRACT_CREATOR_BYTECODE: &str =
include_str!("./res/foo_bar_contract_creator.txt");
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f80fd5b506102208061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80632fc110601461002d575b5f80fd5b61003561004b565b6040516100429190610102565b60405180910390f35b5f806040516100599061007c565b604051809103905ff080158015610072573d5f803e3d5ffd5b5090508091505090565b60cf8061011c83390190565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f6100ca6100c56100c084610088565b6100a7565b610088565b9050919050565b5f6100db826100b0565b9050919050565b5f6100ec826100d1565b9050919050565b6100fc816100e2565b82525050565b5f6020820190506101155f8301846100f3565b9291505056fe6080604052348015600e575f80fd5b5060b580601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063f2c9ecd814602a575b5f80fd5b60306044565b604051603b91906068565b60405180910390f35b5f600a905090565b5f63ffffffff82169050919050565b606281604c565b82525050565b5f60208201905060795f830184605b565b9291505056fea2646970667358221220d061ca6930ff12673467107984883595e5f7ee04e63392aed46124a4bd3c4b4f64736f6c63430008190033a2646970667358221220f849f845d87941120b198faa30df2975ad373cbacfb60c64a7f2c0a2a36b502564736f6c63430008190033
2 changes: 2 additions & 0 deletions frame/evm/precompile/dispatch/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ impl pallet_evm::Config for Test {
type GasLimitPovSizeRatio = ();
type GasLimitStorageGrowthRatio = ();
type Timestamp = Timestamp;
type CreateInnerOriginFilter = ();
type CreateOriginFilter = ();
type WeightInfo = ();
}

Expand Down
Loading
Loading