Skip to content
Merged
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
5 changes: 2 additions & 3 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 @@ -135,7 +135,7 @@ fvm_shared = "4.6.0"
fvm_ipld_encoding = "0.5.2"
fvm_ipld_blockstore = "0.3.0"
fvm_ipld_hamt = "0.10.2"
fvm_ipld_kamt = "0.4.3"
fvm_ipld_kamt = "0.4.4"
fvm_ipld_amt = { version = "0.7.3" }
fvm_ipld_bitfield = "0.7.0"

Expand Down
10 changes: 10 additions & 0 deletions actors/evm/tests/contracts/recall_contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Recall Contract

This directory contains compiled copies of https://github.com/recallnet taken from mainnet contracts.

- Proxy contract: 0xf0438cd20Fa4855997297A9C1299469CA10b58bf
- Implementation contract: 0x1835374384AA51B169c0705DA26A84bB760F2B37

We're using these to reproduce https://github.com/recallnet/contracts/issues/98

These contracts are copyright 2025 the Recall Contributors, available under either the MIT or the Apache-2.0 license.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions actors/evm/tests/contracts/recall_contract/proxy.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
60806040526102a88038038061001481610168565b92833981016040828203126101645781516001600160a01b03811692909190838303610164576020810151906001600160401b03821161016457019281601f8501121561016457835161006e610069826101a1565b610168565b9481865260208601936020838301011161016457815f926020809301865e86010152823b15610152577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a282511561013a575f8091610122945190845af43d15610132573d91610113610069846101a1565b9283523d5f602085013e6101bc565b505b604051608d908161021b8239f35b6060916101bc565b50505034156101245763b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761018d57604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161018d57601f01601f191660200190565b906101e057508051156101d157805190602001fd5b630a12f52160e11b5f5260045ffd5b81511580610211575b6101f1575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156101e956fe60806040525f8073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416368280378136915af43d5f803e156053573d5ff35b3d5ffdfea2646970667358221220d84369ae6f98a27679b5d10b53558f46164239ede3a4126e04298270c4193fd364736f6c634300081a00330000000000000000000000001835374384aa51b169c0705da26a84bb760f2b3700000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044be13f47c000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c341bb76302c76fb57d6fe6c003c4fc68e56cbe5c5a4c04bedf1522a15c7e41a000000000000000000000000000000000000000000000000000000000
88 changes: 88 additions & 0 deletions integration_tests/src/tests/evm_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,94 @@ pub fn evm_staticcall_delegatecall_test(v: &dyn VM) {
}
}

#[allow(non_snake_case)]
#[vm_test]
pub fn evm_constructor_delegatecall_regression_test(v: &dyn VM) {
const IMP_INITCODE: &str =
include_str!("../../../actors/evm/tests/contracts/recall_contract/implementation.hex");
const PROXY_INITCODE: &str =
include_str!("../../../actors/evm/tests/contracts/recall_contract/proxy.hex");

// Create accounts for deployment
let deployer = create_accounts(v, 1, &TokenAmount::from_whole(10_000))[0];

// 1. Deploy the implementation contract
let imp_bytecode = hex::decode(IMP_INITCODE).unwrap();
let imp_deploy_result = v
.execute_message(
&deployer,
&EAM_ACTOR_ADDR,
&TokenAmount::zero(),
fil_actor_eam::Method::CreateExternal as u64,
Some(serialize_ok(&fil_actor_eam::CreateExternalParams(imp_bytecode))),
)
.unwrap();

assert!(
imp_deploy_result.code.is_success(),
"Failed to deploy implementation contract: {}",
imp_deploy_result.message
);

let imp_return: fil_actor_eam::CreateExternalReturn = imp_deploy_result
.ret
.unwrap()
.deserialize()
.expect("Failed to decode implementation deployment results");

// Make sure we deployed an EVM actor
assert_eq!(&v.actor(&Address::new_id(imp_return.actor_id)).unwrap().code, &*EVM_ACTOR_CODE_ID);

// 2. Deploy the proxy contract with implementation address in constructor, replacing the
// mainnet implementation address.
let proxy_initcode_fixed = PROXY_INITCODE.replace(
"1835374384aa51b169c0705da26a84bb760f2b37",
&hex::encode(imp_return.eth_address.0),
);
let proxy_initcode = hex::decode(proxy_initcode_fixed).unwrap();

let proxy_deploy_result = v
.execute_message(
&deployer,
&EAM_ACTOR_ADDR,
&TokenAmount::zero(),
fil_actor_eam::Method::CreateExternal as u64,
Some(serialize_ok(&fil_actor_eam::CreateExternalParams(proxy_initcode))),
)
.unwrap();

assert!(
proxy_deploy_result.code.is_success(),
"Failed to deploy proxy contract: {}",
proxy_deploy_result.message
);

let proxy_return: fil_actor_eam::CreateExternalReturn = proxy_deploy_result
.ret
.unwrap()
.deserialize()
.expect("Failed to decode proxy deployment results");

let proxy_robust_addr = proxy_return.robust_address.unwrap();

// Try to mint:
const PARAMS: &str = "40c10f1900000000000000000000000090f79bf6eb2c4f870365e785982e1f101e93b9060000000000000000000000000000000000000000000000008ac7230489e80000";
let params = hex::decode(PARAMS).unwrap();

let mint_result = v
.execute_message(
&deployer,
&proxy_robust_addr,
&TokenAmount::zero(),
fil_actor_evm::Method::InvokeContract as u64,
Some(serialize_ok(&ContractParams(params))),
)
.unwrap();

assert!(mint_result.code.is_success(), "Failed to mint: {}", mint_result.message);
}

#[allow(non_snake_case)]
#[vm_test]
pub fn evm_init_revert_data_test(v: &dyn VM) {
let account = create_accounts(v, 1, &TokenAmount::from_whole(10_000))[0];
Expand Down
14 changes: 11 additions & 3 deletions test_vm/tests/suite/evm_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use fil_actors_integration_tests::tests::{
evm_call_test, evm_create_test, evm_delegatecall_test, evm_empty_initcode_test,
evm_eth_create_external_test, evm_init_revert_data_test, evm_staticcall_delegatecall_test,
evm_staticcall_test, evm_transient_nested_test, evm_transient_reentry_test,
evm_call_test, evm_constructor_delegatecall_regression_test, evm_create_test,
evm_delegatecall_test, evm_empty_initcode_test, evm_eth_create_external_test,
evm_init_revert_data_test, evm_staticcall_delegatecall_test, evm_staticcall_test,
evm_transient_nested_test, evm_transient_reentry_test,
};
use fil_actors_runtime::test_blockstores::MemoryBlockstore;
use test_vm::TestVM;
Expand Down Expand Up @@ -54,6 +55,13 @@ fn evm_staticcall_delegatecall() {
evm_staticcall_delegatecall_test(&v);
}

#[test]
fn evm_constructor_delegatecall_regression() {
let store = MemoryBlockstore::new();
let v = TestVM::new_with_singletons(store);
evm_constructor_delegatecall_regression_test(&v);
}

#[test]
fn evm_init_revert_data() {
let store = MemoryBlockstore::new();
Expand Down