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::SubStackUnderflow { .. })
|
||||||
| Err(vm::Error::OutOfSubStack { .. })
|
| Err(vm::Error::OutOfSubStack { .. })
|
||||||
| Err(vm::Error::InvalidSubEntry)
|
| Err(vm::Error::InvalidSubEntry)
|
||||||
|
| Err(vm::Error::InvalidCode)
|
||||||
| Ok(FinalizationResult {
|
| Ok(FinalizationResult {
|
||||||
apply_state: false, ..
|
apply_state: false, ..
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -431,6 +431,12 @@ where
|
|||||||
false => Ok(*gas),
|
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
|
self.state
|
||||||
.init_code(&self.origin_info.address, data.to_vec())?;
|
.init_code(&self.origin_info.address, data.to_vec())?;
|
||||||
Ok(*gas - return_cost)
|
Ok(*gas - return_cost)
|
||||||
@ -913,4 +919,46 @@ mod tests {
|
|||||||
Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap()
|
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,
|
pub eip2930_transition: BlockNumber,
|
||||||
/// Number of first block where EIP-3529 rules begin.
|
/// Number of first block where EIP-3529 rules begin.
|
||||||
pub eip3529_transition: BlockNumber,
|
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.
|
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||||
pub dust_protection_transition: BlockNumber,
|
pub dust_protection_transition: BlockNumber,
|
||||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
/// 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.have_subs = block_number >= self.eip2315_transition;
|
||||||
schedule.eip2929 = block_number >= self.eip2929_transition;
|
schedule.eip2929 = block_number >= self.eip2929_transition;
|
||||||
schedule.eip2930 = block_number >= self.eip2930_transition;
|
schedule.eip2930 = block_number >= self.eip2930_transition;
|
||||||
|
schedule.eip3541 = block_number >= self.eip3541_transition;
|
||||||
|
|
||||||
if block_number >= self.eip1884_transition {
|
if block_number >= self.eip1884_transition {
|
||||||
schedule.have_selfbalance = true;
|
schedule.have_selfbalance = true;
|
||||||
@ -388,6 +391,9 @@ impl From<ethjson::spec::Params> for CommonParams {
|
|||||||
eip3529_transition: p
|
eip3529_transition: p
|
||||||
.eip3529_transition
|
.eip3529_transition
|
||||||
.map_or_else(BlockNumber::max_value, Into::into),
|
.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: p
|
||||||
.dust_protection_transition
|
.dust_protection_transition
|
||||||
.map_or_else(BlockNumber::max_value, Into::into),
|
.map_or_else(BlockNumber::max_value, Into::into),
|
||||||
@ -678,6 +684,7 @@ impl Spec {
|
|||||||
params.eip2929_transition,
|
params.eip2929_transition,
|
||||||
params.eip2930_transition,
|
params.eip2930_transition,
|
||||||
params.eip3529_transition,
|
params.eip3529_transition,
|
||||||
|
params.eip3541_transition,
|
||||||
params.dust_protection_transition,
|
params.dust_protection_transition,
|
||||||
params.wasm_activation_transition,
|
params.wasm_activation_transition,
|
||||||
params.wasm_disable_transition,
|
params.wasm_disable_transition,
|
||||||
|
@ -48,6 +48,8 @@ pub enum Error {
|
|||||||
Internal,
|
Internal,
|
||||||
/// When execution tries to modify the state in static context
|
/// When execution tries to modify the state in static context
|
||||||
MutableCallInStaticContext,
|
MutableCallInStaticContext,
|
||||||
|
/// When invalid code was attempted to deploy
|
||||||
|
InvalidCode,
|
||||||
/// Wasm error
|
/// Wasm error
|
||||||
Wasm,
|
Wasm,
|
||||||
/// Contract tried to access past the return data buffer.
|
/// 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::OutOfSubStack { .. } => Error::OutOfSubStack,
|
||||||
VmError::InvalidSubEntry { .. } => Error::InvalidSubEntry,
|
VmError::InvalidSubEntry { .. } => Error::InvalidSubEntry,
|
||||||
VmError::BuiltIn { .. } => Error::BuiltIn,
|
VmError::BuiltIn { .. } => Error::BuiltIn,
|
||||||
|
VmError::InvalidCode => Error::InvalidCode,
|
||||||
VmError::Wasm { .. } => Error::Wasm,
|
VmError::Wasm { .. } => Error::Wasm,
|
||||||
VmError::Internal(_) => Error::Internal,
|
VmError::Internal(_) => Error::Internal,
|
||||||
VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext,
|
VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext,
|
||||||
@ -96,6 +99,7 @@ impl fmt::Display for Error {
|
|||||||
OutOfSubStack => "Subroutine stack overflow",
|
OutOfSubStack => "Subroutine stack overflow",
|
||||||
BuiltIn => "Built-in failed",
|
BuiltIn => "Built-in failed",
|
||||||
InvalidSubEntry => "Invalid subroutine entry",
|
InvalidSubEntry => "Invalid subroutine entry",
|
||||||
|
InvalidCode => "Invalid code",
|
||||||
Wasm => "Wasm runtime error",
|
Wasm => "Wasm runtime error",
|
||||||
Internal => "Internal error",
|
Internal => "Internal error",
|
||||||
MutableCallInStaticContext => "Mutable Call In Static Context",
|
MutableCallInStaticContext => "Mutable Call In Static Context",
|
||||||
@ -124,6 +128,7 @@ impl Encodable for Error {
|
|||||||
SubStackUnderflow => 11,
|
SubStackUnderflow => 11,
|
||||||
OutOfSubStack => 12,
|
OutOfSubStack => 12,
|
||||||
InvalidSubEntry => 13,
|
InvalidSubEntry => 13,
|
||||||
|
InvalidCode => 14,
|
||||||
};
|
};
|
||||||
|
|
||||||
s.append_internal(&value);
|
s.append_internal(&value);
|
||||||
@ -149,6 +154,7 @@ impl Decodable for Error {
|
|||||||
11 => Ok(SubStackUnderflow),
|
11 => Ok(SubStackUnderflow),
|
||||||
12 => Ok(OutOfSubStack),
|
12 => Ok(OutOfSubStack),
|
||||||
13 => Ok(InvalidSubEntry),
|
13 => Ok(InvalidSubEntry),
|
||||||
|
14 => Ok(InvalidCode),
|
||||||
_ => Err(DecoderError::Custom("Invalid error type")),
|
_ => Err(DecoderError::Custom("Invalid error type")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,8 @@ pub struct Params {
|
|||||||
/// See `CommonParams` docs.
|
/// See `CommonParams` docs.
|
||||||
pub eip3529_transition: Option<Uint>,
|
pub eip3529_transition: Option<Uint>,
|
||||||
/// See `CommonParams` docs.
|
/// See `CommonParams` docs.
|
||||||
|
pub eip3541_transition: Option<Uint>,
|
||||||
|
/// See `CommonParams` docs.
|
||||||
pub dust_protection_transition: Option<Uint>,
|
pub dust_protection_transition: Option<Uint>,
|
||||||
/// See `CommonParams` docs.
|
/// See `CommonParams` docs.
|
||||||
pub nonce_cap_increment: Option<Uint>,
|
pub nonce_cap_increment: Option<Uint>,
|
||||||
|
@ -92,6 +92,8 @@ pub enum Error {
|
|||||||
BuiltIn(&'static str),
|
BuiltIn(&'static str),
|
||||||
/// When execution tries to modify the state in static context
|
/// When execution tries to modify the state in static context
|
||||||
MutableCallInStaticContext,
|
MutableCallInStaticContext,
|
||||||
|
/// Invalid code to deploy as a contract
|
||||||
|
InvalidCode,
|
||||||
/// Likely to cause consensus issues.
|
/// Likely to cause consensus issues.
|
||||||
Internal(String),
|
Internal(String),
|
||||||
/// Wasm runtime error
|
/// Wasm runtime error
|
||||||
@ -145,6 +147,7 @@ impl fmt::Display for Error {
|
|||||||
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
|
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
|
||||||
Internal(ref msg) => write!(f, "Internal error: {}", msg),
|
Internal(ref msg) => write!(f, "Internal error: {}", msg),
|
||||||
MutableCallInStaticContext => write!(f, "Mutable call in static context"),
|
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),
|
Wasm(ref msg) => write!(f, "Internal error: {}", msg),
|
||||||
OutOfBounds => write!(f, "Out of bounds"),
|
OutOfBounds => write!(f, "Out of bounds"),
|
||||||
Reverted => write!(f, "Reverted"),
|
Reverted => write!(f, "Reverted"),
|
||||||
|
@ -163,6 +163,8 @@ pub struct Schedule {
|
|||||||
pub eip2930: bool,
|
pub eip2930: bool,
|
||||||
/// Gas used in transaction divided by this number is the maximum refundable amount.
|
/// Gas used in transaction divided by this number is the maximum refundable amount.
|
||||||
pub max_refund_quotient: usize,
|
pub max_refund_quotient: usize,
|
||||||
|
// Enable EIP-3541 rule
|
||||||
|
pub eip3541: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wasm cost table
|
/// Wasm cost table
|
||||||
@ -311,6 +313,7 @@ impl Schedule {
|
|||||||
eip2929: false,
|
eip2929: false,
|
||||||
eip2930: false,
|
eip2930: false,
|
||||||
max_refund_quotient: MAX_REFUND_QUOTIENT,
|
max_refund_quotient: MAX_REFUND_QUOTIENT,
|
||||||
|
eip3541: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +379,8 @@ impl Schedule {
|
|||||||
schedule.sstore_refund_gas = EIP3529_SSTORE_CLEARS_SCHEDULE;
|
schedule.sstore_refund_gas = EIP3529_SSTORE_CLEARS_SCHEDULE;
|
||||||
schedule.max_refund_quotient = EIP3529_MAX_REFUND_QUOTIENT;
|
schedule.max_refund_quotient = EIP3529_MAX_REFUND_QUOTIENT;
|
||||||
|
|
||||||
|
schedule.eip3541 = true;
|
||||||
|
|
||||||
schedule
|
schedule
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,6 +448,7 @@ impl Schedule {
|
|||||||
eip2929: false,
|
eip2929: false,
|
||||||
eip2930: false,
|
eip2930: false,
|
||||||
max_refund_quotient: MAX_REFUND_QUOTIENT,
|
max_refund_quotient: MAX_REFUND_QUOTIENT,
|
||||||
|
eip3541: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user