Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Fix TStore for reverts and in static calls #1811

Merged
merged 4 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,14 @@ impl<'a> CircuitInputStateRef<'a> {
None
}
}
OperationRef(Target::TransientStorage, idx) => {
let operation = &self.block.container.transient_storage[*idx];
if operation.rw().is_write() && operation.reversible() {
Some(OpEnum::TransientStorage(operation.op().reverse()))
} else {
None
}
}
OperationRef(Target::TxAccessListAccount, idx) => {
let operation = &self.block.container.tx_access_list_account[*idx];
if operation.rw().is_write() && operation.reversible() {
Expand Down Expand Up @@ -1436,6 +1444,7 @@ impl<'a> CircuitInputStateRef<'a> {
OpcodeId::RETURNDATACOPY => Some(ExecError::ReturnDataOutOfBounds),
// Break write protection (CALL with value will be handled below)
OpcodeId::SSTORE
| OpcodeId::TSTORE
| OpcodeId::CREATE
| OpcodeId::CREATE2
| OpcodeId::SELFDESTRUCT
Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/evm/opcodes/error_write_protection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl Opcode for ErrorWriteProtection {
// assert op code can only be following codes
assert!([
OpcodeId::SSTORE,
OpcodeId::TSTORE,
OpcodeId::CREATE,
OpcodeId::CREATE2,
OpcodeId::CALL,
Expand Down
7 changes: 5 additions & 2 deletions bus-mapping/src/operation/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ impl OperationContainer {
OperationRef::from((Target::Storage, self.storage.len() - 1))
}
OpEnum::TransientStorage(op) => {
self.transient_storage
.push(Operation::new(rwc, rwc_inner_chunk, rw, op));
self.transient_storage.push(if reversible {
Operation::new_reversible(rwc, rwc_inner_chunk, rw, op)
} else {
Operation::new(rwc, rwc_inner_chunk, rw, op)
});
OperationRef::from((Target::TransientStorage, self.transient_storage.len() - 1))
}
OpEnum::TxAccessListAccount(op) => {
Expand Down
70 changes: 45 additions & 25 deletions zkevm-circuits/src/evm_circuit/execution/error_write_protection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,26 @@ mod test {
Account::mock_code_balance(code)
}

#[derive(Copy, Clone, Debug)]
enum FailureReason {
Sstore,
TStore,
CallWithValue,
}

#[test]
fn test_write_protection() {
// test sstore with write protection error
test_internal_write_protection(false);
// test call with write protection error
test_internal_write_protection(true);
for reason in [
FailureReason::Sstore,
FailureReason::CallWithValue,
FailureReason::TStore,
] {
test_internal_write_protection(reason)
}
}

// ErrorWriteProtection error happen in internal call
fn test_internal_write_protection(is_call: bool) {
fn test_internal_write_protection(reason: FailureReason) {
let mut caller_bytecode = bytecode! {
PUSH1(0)
PUSH1(0)
Expand All @@ -185,26 +195,36 @@ mod test {
PUSH1(0x02)
};

if is_call {
callee_bytecode.append(&bytecode! {
PUSH1(0)
PUSH1(0)
PUSH1(10)
PUSH1(200) // non zero value
PUSH20(Address::repeat_byte(0xff).to_word())
PUSH2(10000) // gas
//this call got error: ErrorWriteProtection
CALL
RETURN
STOP
});
} else {
callee_bytecode.append(&bytecode! {
// this SSTORE got error: ErrorWriteProtection
SSTORE
STOP
});
}
match reason {
FailureReason::CallWithValue => {
callee_bytecode.append(&bytecode! {
PUSH1(0)
PUSH1(0)
PUSH1(10)
PUSH1(200) // non zero value
PUSH20(Address::repeat_byte(0xff).to_word())
PUSH2(10000) // gas
//this call got error: ErrorWriteProtection
CALL
RETURN
STOP
});
}
FailureReason::Sstore => {
callee_bytecode.append(&bytecode! {
// this SSTORE got error: ErrorWriteProtection
SSTORE
STOP
});
}
FailureReason::TStore => {
callee_bytecode.append(&bytecode! {
// this TSTORE got error: ErrorWriteProtection
TSTORE
STOP
});
}
};

test_ok(
Account::mock_100_ether(caller_bytecode),
Expand Down
32 changes: 32 additions & 0 deletions zkevm-circuits/src/evm_circuit/execution/tstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,36 @@ mod test {

CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

#[test]
fn test_revert() {
let key = Word::from(34);
let value = Word::from(100);

let bytecode = bytecode! {
PUSH32(value)
PUSH32(key)
TSTORE
PUSH32(0)
PUSH32(0)
REVERT
};
let ctx = TestContext::<2, 1>::new(
None,
|accs| {
accs[0]
.address(MOCK_ACCOUNTS[0])
.balance(Word::from(10u64.pow(19)))
.code(bytecode);
accs[1]
.address(MOCK_ACCOUNTS[1])
.balance(Word::from(10u64.pow(19)));
},
tx_from_1_to_0,
|block, _txs| block,
)
.unwrap();

CircuitTestBuilder::new_from_test_ctx(ctx).run();
}
}
Loading