EIP 3541 (#422)
* Add EIP-3541 transition block parameter * Implement EIP-3541 * Add a unit test for EIP-3541 * Add error type for attempt to deploy invalid code * fmt
This commit is contained in:
parent
f14d3e5a5c
commit
144b2293a2
@ -444,6 +444,7 @@ impl<'a> CallCreateExecutive<'a> {
|
||||
| Err(vm::Error::SubStackUnderflow { .. })
|
||||
| Err(vm::Error::OutOfSubStack { .. })
|
||||
| Err(vm::Error::InvalidSubEntry)
|
||||
| Err(vm::Error::InvalidCode)
|
||||
| Ok(FinalizationResult {
|
||||
apply_state: false, ..
|
||||
}) => {
|
||||
|
@ -431,6 +431,12 @@ where
|
||||
false => Ok(*gas),
|
||||
};
|
||||
}
|
||||
if self.schedule.eip3541 && data.get(0) == Some(&0xefu8) {
|
||||
return match self.schedule.exceptional_failed_code_deposit {
|
||||
true => Err(vm::Error::InvalidCode),
|
||||
false => Ok(*gas),
|
||||
};
|
||||
}
|
||||
self.state
|
||||
.init_code(&self.origin_info.address, data.to_vec())?;
|
||||
Ok(*gas - return_cost)
|
||||
@ -913,4 +919,46 @@ mod tests {
|
||||
Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eip_3541() {
|
||||
let call_ret = |schedule: Schedule, data: &ReturnData| {
|
||||
let mut setup = TestSetup::default();
|
||||
setup.schedule = schedule;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin = get_test_origin();
|
||||
let ext = Externalities::new(
|
||||
&mut setup.state,
|
||||
&setup.env_info,
|
||||
&setup.machine,
|
||||
&setup.schedule,
|
||||
0,
|
||||
0,
|
||||
&origin,
|
||||
&mut setup.sub_state,
|
||||
OutputPolicy::InitContract,
|
||||
&mut tracer,
|
||||
&mut vm_tracer,
|
||||
false,
|
||||
);
|
||||
ext.ret(&U256::from(10000), &data, true)
|
||||
};
|
||||
|
||||
let data = ReturnData::new(vec![0xefu8], 0, 1);
|
||||
|
||||
let result = call_ret(Schedule::new_berlin(), &data);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let result = call_ret(Schedule::new_london(), &data);
|
||||
assert!(result.is_err());
|
||||
|
||||
let data = ReturnData::new(vec![0xefu8, 0x00u8, 0x00u8], 0, 3);
|
||||
let result = call_ret(Schedule::new_london(), &data);
|
||||
assert!(result.is_err());
|
||||
|
||||
let data = ReturnData::new(vec![0xee], 0, 1);
|
||||
let result = call_ret(Schedule::new_london(), &data);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +141,8 @@ pub struct CommonParams {
|
||||
pub eip2930_transition: BlockNumber,
|
||||
/// Number of first block where EIP-3529 rules begin.
|
||||
pub eip3529_transition: BlockNumber,
|
||||
/// Number of first block where EIP-3541 rule begins.
|
||||
pub eip3541_transition: BlockNumber,
|
||||
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||
pub dust_protection_transition: BlockNumber,
|
||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
||||
@ -217,6 +219,7 @@ impl CommonParams {
|
||||
schedule.have_subs = block_number >= self.eip2315_transition;
|
||||
schedule.eip2929 = block_number >= self.eip2929_transition;
|
||||
schedule.eip2930 = block_number >= self.eip2930_transition;
|
||||
schedule.eip3541 = block_number >= self.eip3541_transition;
|
||||
|
||||
if block_number >= self.eip1884_transition {
|
||||
schedule.have_selfbalance = true;
|
||||
@ -388,6 +391,9 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
eip3529_transition: p
|
||||
.eip3529_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip3541_transition: p
|
||||
.eip3541_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
dust_protection_transition: p
|
||||
.dust_protection_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
@ -678,6 +684,7 @@ impl Spec {
|
||||
params.eip2929_transition,
|
||||
params.eip2930_transition,
|
||||
params.eip3529_transition,
|
||||
params.eip3541_transition,
|
||||
params.dust_protection_transition,
|
||||
params.wasm_activation_transition,
|
||||
params.wasm_disable_transition,
|
||||
|
@ -48,6 +48,8 @@ pub enum Error {
|
||||
Internal,
|
||||
/// When execution tries to modify the state in static context
|
||||
MutableCallInStaticContext,
|
||||
/// When invalid code was attempted to deploy
|
||||
InvalidCode,
|
||||
/// Wasm error
|
||||
Wasm,
|
||||
/// Contract tried to access past the return data buffer.
|
||||
@ -68,6 +70,7 @@ impl<'a> From<&'a VmError> for Error {
|
||||
VmError::OutOfSubStack { .. } => Error::OutOfSubStack,
|
||||
VmError::InvalidSubEntry { .. } => Error::InvalidSubEntry,
|
||||
VmError::BuiltIn { .. } => Error::BuiltIn,
|
||||
VmError::InvalidCode => Error::InvalidCode,
|
||||
VmError::Wasm { .. } => Error::Wasm,
|
||||
VmError::Internal(_) => Error::Internal,
|
||||
VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext,
|
||||
@ -96,6 +99,7 @@ impl fmt::Display for Error {
|
||||
OutOfSubStack => "Subroutine stack overflow",
|
||||
BuiltIn => "Built-in failed",
|
||||
InvalidSubEntry => "Invalid subroutine entry",
|
||||
InvalidCode => "Invalid code",
|
||||
Wasm => "Wasm runtime error",
|
||||
Internal => "Internal error",
|
||||
MutableCallInStaticContext => "Mutable Call In Static Context",
|
||||
@ -124,6 +128,7 @@ impl Encodable for Error {
|
||||
SubStackUnderflow => 11,
|
||||
OutOfSubStack => 12,
|
||||
InvalidSubEntry => 13,
|
||||
InvalidCode => 14,
|
||||
};
|
||||
|
||||
s.append_internal(&value);
|
||||
@ -149,6 +154,7 @@ impl Decodable for Error {
|
||||
11 => Ok(SubStackUnderflow),
|
||||
12 => Ok(OutOfSubStack),
|
||||
13 => Ok(InvalidSubEntry),
|
||||
14 => Ok(InvalidCode),
|
||||
_ => Err(DecoderError::Custom("Invalid error type")),
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,8 @@ pub struct Params {
|
||||
/// See `CommonParams` docs.
|
||||
pub eip3529_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
pub eip3541_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
pub dust_protection_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
pub nonce_cap_increment: Option<Uint>,
|
||||
|
@ -92,6 +92,8 @@ pub enum Error {
|
||||
BuiltIn(&'static str),
|
||||
/// When execution tries to modify the state in static context
|
||||
MutableCallInStaticContext,
|
||||
/// Invalid code to deploy as a contract
|
||||
InvalidCode,
|
||||
/// Likely to cause consensus issues.
|
||||
Internal(String),
|
||||
/// Wasm runtime error
|
||||
@ -145,6 +147,7 @@ impl fmt::Display for Error {
|
||||
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
|
||||
Internal(ref msg) => write!(f, "Internal error: {}", msg),
|
||||
MutableCallInStaticContext => write!(f, "Mutable call in static context"),
|
||||
InvalidCode => write!(f, "Invalid code to deploy as a contract"),
|
||||
Wasm(ref msg) => write!(f, "Internal error: {}", msg),
|
||||
OutOfBounds => write!(f, "Out of bounds"),
|
||||
Reverted => write!(f, "Reverted"),
|
||||
|
@ -163,6 +163,8 @@ pub struct Schedule {
|
||||
pub eip2930: bool,
|
||||
/// Gas used in transaction divided by this number is the maximum refundable amount.
|
||||
pub max_refund_quotient: usize,
|
||||
// Enable EIP-3541 rule
|
||||
pub eip3541: bool,
|
||||
}
|
||||
|
||||
/// Wasm cost table
|
||||
@ -311,6 +313,7 @@ impl Schedule {
|
||||
eip2929: false,
|
||||
eip2930: false,
|
||||
max_refund_quotient: MAX_REFUND_QUOTIENT,
|
||||
eip3541: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,6 +379,8 @@ impl Schedule {
|
||||
schedule.sstore_refund_gas = EIP3529_SSTORE_CLEARS_SCHEDULE;
|
||||
schedule.max_refund_quotient = EIP3529_MAX_REFUND_QUOTIENT;
|
||||
|
||||
schedule.eip3541 = true;
|
||||
|
||||
schedule
|
||||
}
|
||||
|
||||
@ -443,6 +448,7 @@ impl Schedule {
|
||||
eip2929: false,
|
||||
eip2930: false,
|
||||
max_refund_quotient: MAX_REFUND_QUOTIENT,
|
||||
eip3541: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user