Skip to content

Commit

Permalink
feat: persist transferred MNTs for Delegate Calls
Browse files Browse the repository at this point in the history
fix: Precompile now returns Transferred Tokens from Call and not Tx

test: get Call Values as a contract

refactor: remove the now-redundant EOA-to-Precompile test
refactor: use a more suggestive naming in the SabVM tests
  • Loading branch information
IaroslavMazur committed Aug 23, 2024
1 parent c8e31b3 commit d2c7760
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 189 deletions.
14 changes: 2 additions & 12 deletions crates/interpreter/src/instructions/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,7 @@ pub fn extdelegatecall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpret
target_address,
caller: interpreter.contract.target_address,
bytecode_address: target_address,
values: CallValues::Apparent(vec![
(TokenTransfer {
id: BASE_TOKEN_ID,
amount: interpreter.contract.call_value,
}),
]),
values: CallValues::Apparent(interpreter.contract.call_values.clone()),
// TODO(EOF) should be EofDelegateCall?
scheme: CallScheme::DelegateCall,
is_static: interpreter.is_static,
Expand Down Expand Up @@ -527,12 +522,7 @@ pub fn delegate_call<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter
target_address: interpreter.contract.target_address,
caller: interpreter.contract.caller,
bytecode_address: to,
values: CallValues::Apparent(vec![
(TokenTransfer {
id: BASE_TOKEN_ID,
amount: interpreter.contract.call_value,
}),
]),
values: CallValues::Apparent(interpreter.contract.call_values.clone()),
scheme: CallScheme::DelegateCall,
is_static: interpreter.is_static,
is_eof: false,
Expand Down
12 changes: 10 additions & 2 deletions crates/interpreter/src/instructions/system.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
gas,
primitives::{Spec, B256, KECCAK_EMPTY, U256},
primitives::{Spec, B256, BASE_TOKEN_ID, KECCAK_EMPTY, U256},
Host, InstructionResult, Interpreter,
};
use core::ptr;
Expand Down Expand Up @@ -88,7 +88,15 @@ pub fn calldatasize<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut

pub fn callvalue<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push!(interpreter, interpreter.contract.call_value);
push!(
interpreter,
interpreter
.contract
.call_values
.iter()
.find(|tt| tt.id == BASE_TOKEN_ID)
.map_or(U256::ZERO, |tt| tt.amount)
);
}

pub fn calldatacopy<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
Expand Down
20 changes: 8 additions & 12 deletions crates/interpreter/src/interpreter/contract.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use revm_primitives::BASE_TOKEN_ID;
use revm_primitives::TokenTransfer;

use super::analysis::to_analysed;
use crate::{
primitives::{Address, Bytecode, Bytes, Env, TransactTo, B256, U256},
primitives::{Address, Bytecode, Bytes, Env, TransactTo, B256},
CallInputs,
};

Expand All @@ -21,8 +21,8 @@ pub struct Contract {
pub target_address: Address,
/// Caller of the EVM.
pub caller: Address,
/// Value send to contract from transaction or from CALL opcodes.
pub call_value: U256,
/// Values sent to the contract from transaction or from CALL opcodes.
pub call_values: Vec<TokenTransfer>,
}

impl Contract {
Expand All @@ -34,7 +34,7 @@ impl Contract {
hash: Option<B256>,
target_address: Address,
caller: Address,
call_value: U256,
call_values: Vec<TokenTransfer>,
) -> Self {
let bytecode = to_analysed(bytecode);

Expand All @@ -44,7 +44,7 @@ impl Contract {
hash,
target_address,
caller,
call_value,
call_values,
}
}

Expand All @@ -61,7 +61,7 @@ impl Contract {
hash,
contract_address,
env.tx.caller,
env.tx.get_base_transfer_value(),
env.tx.transferred_tokens.clone(),
)
}

Expand All @@ -79,11 +79,7 @@ impl Contract {
hash,
call_context.target_address,
call_context.caller,
call_context
.call_values()
.iter()
.find(|tt| tt.id == BASE_TOKEN_ID)
.map_or(U256::ZERO, |tt| tt.amount), //TODO: pass all of the transferred tokens when contract deployment is permissionless
call_context.call_values(),
)
}

Expand Down
19 changes: 15 additions & 4 deletions crates/revm/src/context/inner_evm_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use crate::{
keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env,
Eof, HashSet, Spec,
SpecId::{self, *},
B256, U256,
TokenTransfer, B256, BASE_TOKEN_ID, U256,
},
FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT,
};
use std::boxed::Box;
use std::{boxed::Box, vec};

/// EVM contexts contains data that EVM needs for execution.
#[derive(Debug)]
Expand Down Expand Up @@ -289,7 +289,12 @@ impl<DB: Database> InnerEvmContext<DB> {
None,
inputs.created_address,
inputs.caller,
inputs.value,
vec![
(TokenTransfer {
id: BASE_TOKEN_ID,
amount: inputs.value,
}),
],
);

let mut interpreter = Interpreter::new(contract, inputs.gas_limit, false);
Expand Down Expand Up @@ -406,13 +411,19 @@ impl<DB: Database> InnerEvmContext<DB> {

let bytecode = Bytecode::new_raw(inputs.init_code.clone());

// TODO: adapt for MNTs when the contract deployment is permissionless
let contract = Contract::new(
Bytes::new(),
bytecode,
Some(init_code_hash),
created_address,
inputs.caller,
inputs.value,
vec![
(TokenTransfer {
id: BASE_TOKEN_ID,
amount: inputs.value,
}),
],
);

Ok(FrameOrResult::new_create_frame(
Expand Down
Loading

0 comments on commit d2c7760

Please sign in to comment.