Skip to content

Commit

Permalink
Fix: EAM: Successfully create actors over placeholders (#1058)
Browse files Browse the repository at this point in the history
  • Loading branch information
arajasek authored Jan 14, 2023
1 parent 757d9e9 commit cc264f7
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
12 changes: 9 additions & 3 deletions actors/eam/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,19 @@ fn create_actor(
RawBytes::serialize(EvmConstructorParams { creator, initcode: initcode.into() })?;
let value = rt.message().value_received();

// Try to resurrect it if it already exists.
let f4_addr = Address::new_delegated(EAM_ACTOR_ID, &new_addr.0).unwrap();

if let Some(id) = rt.resolve_address(&f4_addr) {
rt.send(&Address::new_id(id), RESURRECT_METHOD, constructor_params.into(), value)?;
return Ok(Return { actor_id: id, robust_address: None, eth_address: new_addr });
// Try to resurrect it if it is already an EVM actor (must be "dead")
let caller_code_cid = rt.get_actor_code_cid(&id).expect("failed to lookup actor code");
if let Some(Type::EVM) = rt.resolve_builtin_actor_type(&caller_code_cid) {
rt.send(&Address::new_id(id), RESURRECT_METHOD, constructor_params.into(), value)?;
return Ok(Return { actor_id: id, robust_address: None, eth_address: new_addr });
}
}

// If the f4 address wasn't resolved, or resolved to something other than an EVM actor, we try
// to construct it "normally".
let init_params = Exec4Params {
code_cid: rt.get_code_cid_for_type(Type::EVM),
constructor_params,
Expand Down
75 changes: 73 additions & 2 deletions actors/eam/tests/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ use eam::{
compute_address_create, Create2Params, CreateParams, EthAddress, EvmConstructorParams, Return,
};
use fil_actor_eam as eam;
use fil_actor_eam::CreateExternalParams;
use fil_actors_runtime::runtime::builtins::Type;
use fil_actors_runtime::runtime::Primitives;
use fil_actors_runtime::test_utils::{
expect_empty, MockRuntime, EVM_ACTOR_CODE_ID, SYSTEM_ACTOR_CODE_ID,
expect_empty, MockRuntime, ETHACCOUNT_ACTOR_CODE_ID, EVM_ACTOR_CODE_ID,
PLACEHOLDER_ACTOR_CODE_ID, SYSTEM_ACTOR_CODE_ID,
};
use fil_actors_runtime::{INIT_ACTOR_ADDR, SYSTEM_ACTOR_ADDR};
use fvm_ipld_encoding::ipld_block::IpldBlock;
Expand All @@ -17,7 +19,7 @@ use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;

#[test]
fn call_create() {
fn call_create_new() {
let mut rt = construct_and_verify();

let id_addr = Address::new_id(110);
Expand Down Expand Up @@ -77,6 +79,74 @@ fn call_create() {
rt.verify();
}

#[test]
fn call_create_external_over_placeholder() {
let mut rt = construct_and_verify();

let caller_id_addr = Address::new_id(110);
let caller_eth_addr =
eam::EthAddress(hex_literal::hex!("CAFEB0BA00000000000000000000000000000000"));
let caller_f4_eth_addr = Address::new_delegated(10, &caller_eth_addr.0).unwrap();
rt.add_delegated_address(caller_id_addr, caller_f4_eth_addr);

// Accounts and EthAccounts are the valid caller types for CreateExternal
rt.set_caller(*ETHACCOUNT_ACTOR_CODE_ID, caller_id_addr);
rt.set_origin(caller_id_addr);

let target_id_addr = Address::new_id(111);
let target_eth_addr = compute_address_create(&rt, &caller_eth_addr, 0);
let target_f4_eth_addr = Address::new_delegated(10, &target_eth_addr.0).unwrap();
rt.add_delegated_address(target_id_addr, target_f4_eth_addr);
rt.set_address_actor_type(target_id_addr, *PLACEHOLDER_ACTOR_CODE_ID);

let initcode = vec![0xff];

let create_params = CreateExternalParams(initcode.clone());

let evm_params = EvmConstructorParams { creator: caller_eth_addr, initcode: initcode.into() };

let params = Exec4Params {
code_cid: *EVM_ACTOR_CODE_ID,
constructor_params: RawBytes::serialize(evm_params).unwrap(),
subaddress: target_eth_addr.0[..].to_owned().into(),
};

let send_return = Exec4Return {
id_address: Address::new_id(111),
robust_address: Address::new_actor(&[0xde, 0xad, 0xbe, 0xef]),
};
let send_return_ser = IpldBlock::serialize_cbor(&send_return).unwrap();

rt.expect_send(
INIT_ACTOR_ADDR,
EXEC4_METHOD,
IpldBlock::serialize_cbor(&params).unwrap(),
TokenAmount::from_atto(0),
send_return_ser,
ExitCode::OK,
);

rt.expect_validate_caller_addr(vec![caller_id_addr]);
let result = rt
.call::<eam::EamActor>(
eam::Method::CreateExternal as u64,
IpldBlock::serialize_cbor(&create_params).unwrap(),
)
.unwrap()
.unwrap()
.deserialize::<Return>()
.unwrap();

let expected_return = Return {
actor_id: target_id_addr.id().unwrap(),
robust_address: Some(send_return.robust_address),
eth_address: target_eth_addr,
};

assert_eq!(result, expected_return);
rt.verify();
}

#[test]
fn call_resurrect() {
let mut rt = construct_and_verify();
Expand All @@ -93,6 +163,7 @@ fn call_resurrect() {
let target_eth_addr = compute_address_create(&rt, &caller_eth_addr, 0);
let target_f4_eth_addr = Address::new_delegated(10, &target_eth_addr.0).unwrap();
rt.add_delegated_address(target_id_addr, target_f4_eth_addr);
rt.set_address_actor_type(target_id_addr, *EVM_ACTOR_CODE_ID);

rt.expect_validate_caller_type(vec![Type::EVM]);

Expand Down
6 changes: 6 additions & 0 deletions actors/evm/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ use cid::Cid;
use evm::interpreter::U256;
use evm::interpreter::{address::EthAddress, StatusCode};
use fil_actor_evm as evm;
use fil_actor_evm::State;
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::{
test_utils::{self, *},
ActorError, EAM_ACTOR_ID, INIT_ACTOR_ADDR,
};
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_ipld_encoding::{BytesDe, BytesSer};
use fvm_shared::{address::Address, IDENTITY_HASH, IPLD_RAW};
Expand Down Expand Up @@ -55,6 +58,9 @@ pub fn init_construct_and_verify<F: FnOnce(&mut MockRuntime)>(
)
.unwrap()
.is_none());
let evm_st: State = rt.state().unwrap();
let evm_code = rt.store.get(&evm_st.bytecode).unwrap().unwrap();
println!("{:?}", evm_code);
rt.verify();

rt
Expand Down

0 comments on commit cc264f7

Please sign in to comment.