From 0ec1daa329d9b498b4fb775c866138e78c593093 Mon Sep 17 00:00:00 2001
From: Wei Tang <wei@that.world>
Date: Fri, 8 Apr 2022 02:37:36 +0200
Subject: [PATCH] Add option to initiate a top-level DELEGATECALL

---
 src/executor/stack/executor.rs | 63 ++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/src/executor/stack/executor.rs b/src/executor/stack/executor.rs
index 8eea59d9a..b9ef57167 100644
--- a/src/executor/stack/executor.rs
+++ b/src/executor/stack/executor.rs
@@ -483,6 +483,57 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
 		data: Vec<u8>,
 		gas_limit: u64,
 		access_list: Vec<(H160, Vec<H256>)>,
+	) -> (ExitReason, Vec<u8>) {
+		let context = Context {
+			caller,
+			address,
+			apparent_value: value,
+		};
+
+		let transfer = 	Some(Transfer {
+			source: caller,
+			target: address,
+			value,
+		});
+
+		self.transact_call_with_context(caller, address, data, gas_limit, access_list, context, transfer)
+	}
+
+	/// Execute a `DELEGATECALL` transaction with a given caller, address, value and
+	/// gas limit and data.
+	///
+	/// Takes in an additional `access_list` parameter for EIP-2930 which was
+	/// introduced in the Ethereum Berlin hard fork. If you do not wish to use
+	/// this functionality, just pass in an empty vector.
+	pub fn transact_delegatecall(
+		&mut self,
+		caller: H160,
+		address: H160,
+		value: U256,
+		data: Vec<u8>,
+		gas_limit: u64,
+		access_list: Vec<(H160, Vec<H256>)>,
+	) -> (ExitReason, Vec<u8>) {
+		let context = Context {
+			caller,
+			address: caller,
+			apparent_value: value,
+		};
+
+		let transfer = None;
+
+		self.transact_call_with_context(caller, address, data, gas_limit, access_list, context, transfer)
+	}
+
+	fn transact_call_with_context(
+		&mut self,
+		caller: H160,
+		address: H160,
+		data: Vec<u8>,
+		gas_limit: u64,
+		access_list: Vec<(H160, Vec<H256>)>,
+		context: Context,
+		transfer: Option<Transfer>,
 	) -> (ExitReason, Vec<u8>) {
 		event!(TransactCall {
 			caller,
@@ -509,19 +560,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
 
 		self.state.inc_nonce(caller);
 
-		let context = Context {
-			caller,
-			address,
-			apparent_value: value,
-		};
-
 		match self.call_inner(
 			address,
-			Some(Transfer {
-				source: caller,
-				target: address,
-				value,
-			}),
+			transfer,
 			data,
 			Some(gas_limit),
 			false,