Skip to content

Commit

Permalink
tests(parity): add delegatecall + suicide
Browse files Browse the repository at this point in the history
Signed-off-by: jsvisa <delweng@gmail.com>
  • Loading branch information
jsvisa committed Sep 7, 2024
1 parent 42a74e7 commit 7af0add
Showing 1 changed file with 130 additions and 0 deletions.
130 changes: 130 additions & 0 deletions tests/it/parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,133 @@ fn test_parity_statediff_blob_commit() {
assert!(!state_diff.contains_key(&to));
assert!(state_diff.contains_key(&caller));
}

#[test]
fn test_parity_delegatecall_selfdestruct() {
/*
contract DelegateCall {
constructor() payable {}
function close(address target) public {
(bool success,) = target.delegatecall(abi.encodeWithSignature("close()"));
require(success, "Delegatecall failed");
}
}
contract SelfDestructTarget {
function close() public {
selfdestruct(payable(msg.sender));
}
}
*/

// DelegateCall contract bytecode
let delegate_code = hex!("6080604052348015600e575f80fd5b506103158061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063c74073a11461002d575b5f80fd5b610047600480360381019061004291906101d4565b610049565b005b5f8173ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f43d726d6000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516100f19190610251565b5f60405180830381855af49150503d805f8114610129576040519150601f19603f3d011682016040523d82523d5f602084013e61012e565b606091505b5050905080610172576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610169906102c1565b60405180910390fd5b5050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101a38261017a565b9050919050565b6101b381610199565b81146101bd575f80fd5b50565b5f813590506101ce816101aa565b92915050565b5f602082840312156101e9576101e8610176565b5b5f6101f6848285016101c0565b91505092915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61022b826101ff565b6102358185610209565b9350610245818560208601610213565b80840191505092915050565b5f61025c8284610221565b915081905092915050565b5f82825260208201905092915050565b7f44656c656761746563616c6c206661696c6564000000000000000000000000005f82015250565b5f6102ab601383610267565b91506102b682610277565b602082019050919050565b5f6020820190508181035f8301526102d88161029f565b905091905056fea2646970667358221220f6409a1a1bfa02cbcb4d9818e921686c97eed1566fbd60951a91d232035e046c64736f6c634300081a0033");

// SelfDestructTarget contract bytecode
let target_code = hex!("6080604052348015600e575f80fd5b50608180601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806343d726d614602a575b5f80fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea26469706673582212202ecd1d2f481d093cc2831fe0350ce1fe0bc42bc5cf34eb0a9e40a83b564eb59464736f6c634300081a0033");

let deployer = address!("341348115259a8bf69f1f50101c227fced83bac6");
let mut db = CacheDB::new(EmptyDB::default());

let cfg = CfgEnvWithHandlerCfg::new(CfgEnv::default(), HandlerCfg::new(SpecId::CANCUN));

// Deploy DelegateCall contract
let env = EnvWithHandlerCfg::new_with_cfg_env(
cfg.clone(),
BlockEnv::default(),
TxEnv {
caller: deployer,
gas_limit: 1000000,
transact_to: TransactTo::Create,
data: delegate_code.into(),
..Default::default()
},
);

let mut insp = TracingInspector::new(TracingInspectorConfig::default_parity());
let (res, _) = inspect(&mut db, env, &mut insp).unwrap();
let delegate_addr = match res.result {
ExecutionResult::Success { output, .. } => match output {
Output::Create(_, addr) => addr.unwrap(),
_ => panic!("Create failed"),
},
_ => panic!("Execution failed"),
};
db.commit(res.state);

// Deploy SelfDestructTarget contract
let env = EnvWithHandlerCfg::new_with_cfg_env(
cfg.clone(),
BlockEnv::default(),
TxEnv {
caller: deployer,
gas_limit: 1000000,
transact_to: TransactTo::Create,
data: target_code.into(),
..Default::default()
},
);

let mut insp = TracingInspector::new(TracingInspectorConfig::default_parity());
let (res, _) = inspect(&mut db, env, &mut insp).unwrap();
let target_addr = match res.result {
ExecutionResult::Success { output, .. } => match output {
Output::Create(_, addr) => addr.unwrap(),
_ => panic!("Create failed"),
},
_ => panic!("Execution failed"),
};
db.commit(res.state);

// Prepare the input data for the close(address) function call
let mut input_data = hex!("c74073a1").to_vec(); // keccak256("close(address)")[:4]
input_data.extend_from_slice(&[0u8; 12]); // Pad with zeros
input_data.extend_from_slice(target_addr.as_slice());

// Call DelegateCall contract with SelfDestructTarget address
let mut insp = TracingInspector::new(TracingInspectorConfig::default_parity());
let env = EnvWithHandlerCfg::new_with_cfg_env(
cfg,
BlockEnv::default(),
TxEnv {
caller: deployer,
gas_limit: 1000000,
transact_to: TransactTo::Call(delegate_addr),
data: input_data.into(),
..Default::default()
},
);

let (res, _) = inspect(&mut db, env, &mut insp).unwrap();
assert!(res.result.is_success());

let traces =
insp.into_parity_builder().into_localized_transaction_traces(TransactionInfo::default());

assert_eq!(traces.len(), 3);

let trace0 = &traces[0].trace;
assert!(trace0.action.is_call());
assert_eq!(trace0.trace_address.len(), 0);
assert_eq!(trace0.subtraces, 1);
let action0 = trace0.action.as_call().unwrap();
assert_eq!(action0.call_type, CallType::Call);
assert_eq!(action0.from, deployer);
assert_eq!(action0.to, delegate_addr);

let trace1 = &traces[1].trace;
assert!(trace1.action.is_call());
assert_eq!(trace1.trace_address, vec![0]);
assert_eq!(trace1.subtraces, 1);
let action1 = trace1.action.as_call().unwrap();
assert_eq!(action1.call_type, CallType::DelegateCall);
assert_eq!(action1.from, delegate_addr);
assert_eq!(action1.to, target_addr);

let trace2 = &traces[2].trace;
assert!(trace2.action.is_selfdestruct());
assert_eq!(trace2.trace_address, vec![0, 0]);
assert_eq!(trace2.subtraces, 0);
let action2 = trace2.action.as_selfdestruct().unwrap();
assert_eq!(action2.address, delegate_addr);
assert_eq!(action2.refund_address, deployer);
}

0 comments on commit 7af0add

Please sign in to comment.