SSTORE refund (#1018)

* SSTORE refund

* SSTORE refund

* Minor
This commit is contained in:
wborgeaud 2023-05-11 14:18:34 +02:00 committed by GitHub
parent c134b59763
commit 944d4a2460
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 6 deletions

View File

@ -15,8 +15,36 @@ global sys_gas:
%mload_context_metadata(@CTX_METADATA_GAS_LIMIT)
%endmacro
// Charge gas. Faults if we exceed the limit for the current context.
// TODO: `%refund_gas` and `refund_gas_hook` are hooks used for debugging. They should be removed at some point and `refund_gas_original` renamed to `refund_gas`.
%macro refund_gas
PUSH %%after %jump(refund_gas_hook)
%%after:
%refund_gas_original
%endmacro
global refund_gas_hook:
JUMP
%macro refund_gas_original
// stack: amount
%mload_global_metadata(@GLOBAL_METADATA_REFUND_COUNTER)
ADD
%mstore_global_metadata(@GLOBAL_METADATA_REFUND_COUNTER)
%endmacro
// TODO: `%charge_gas` and `charge_gas_hook` are hooks used for debugging. They should be removed at some point and `charge_gas_original` renamed to `charge_gas`.
%macro charge_gas
PUSH %%after %jump(charge_gas_hook)
%%after:
%charge_gas_original
%endmacro
global charge_gas_hook:
JUMP
// Charge gas. Faults if we exceed the limit for the current context.
%macro charge_gas_original
// stack: gas, kexit_info
%shl_const(192)
ADD

View File

@ -278,7 +278,7 @@ global process_message_txn_after_call:
// stack: used_gas, leftover_gas
%mload_global_metadata(@GLOBAL_METADATA_REFUND_COUNTER)
// stack: refund, used_gas, leftover_gas
DUP2 %div_const(2) // max_refund = used_gas/2
DUP2 %div_const(@MAX_REFUND_QUOTIENT) // max_refund = used_gas/5
// stack: max_refund, refund, used_gas, leftover_gas
%min
%stack (refund, used_gas, leftover_gas) -> (leftover_gas, refund, refund, used_gas)

View File

@ -35,9 +35,54 @@ sstore_warm:
%add_const(@GAS_WARMACCESS)
sstore_charge_gas:
%stack (gas, original_value, current_value, kexit_info, slot, value) -> (gas, kexit_info, current_value, slot, value)
%stack (gas, original_value, current_value, kexit_info, slot, value) -> (gas, kexit_info, current_value, value, original_value, slot)
%charge_gas
sstore_refund:
%stack (kexit_info, current_value, value, original_value, slot) -> (current_value, value, current_value, value, original_value, slot, kexit_info)
EQ %jumpi(sstore_no_refund)
%stack (current_value, value, original_value, slot, kexit_info) -> (current_value, original_value, current_value, value, original_value, slot, kexit_info)
EQ %jumpi(sstore_refund_original)
%stack (current_value, value, original_value, slot, kexit_info) -> (original_value, current_value, value, original_value, slot, kexit_info)
ISZERO %jumpi(sstore_dirty_reset)
%stack (current_value, value, original_value, slot, kexit_info) -> (current_value, current_value, value, original_value, slot, kexit_info)
ISZERO %jumpi(sstore_dirty_clear1)
%stack (current_value, value, original_value, slot, kexit_info) -> (value, current_value, value, original_value, slot, kexit_info)
ISZERO %jumpi(sstore_dirty_clear2)
%jump(sstore_dirty_reset)
sstore_dirty_clear1:
PUSH @REFUND_SCLEAR PUSH 0 SUB %refund_gas
%jump(sstore_dirty_reset)
sstore_dirty_clear2:
PUSH @REFUND_SCLEAR %refund_gas
sstore_dirty_reset:
%stack (current_value, value, original_value, slot, kexit_info) -> (original_value, value, current_value, value, original_value, slot, kexit_info)
EQ %jumpi(sstore_dirty_reset2)
%jump(sstore_no_refund)
sstore_dirty_reset2:
%stack (current_value, value, original_value, slot, kexit_info) -> (original_value, current_value, value, original_value, slot, kexit_info)
ISZERO %jumpi(sstore_dirty_reset_sset)
PUSH @GAS_WARMACCESS PUSH @GAS_SRESET SUB %refund_gas
%jump(sstore_no_refund)
sstore_dirty_reset_sset:
PUSH @GAS_WARMACCESS PUSH @GAS_SSET SUB %refund_gas
%jump(sstore_no_refund)
sstore_refund_original:
%stack (current_value, value, original_value, slot, kexit_info) -> (value, current_value, value, original_value, slot, kexit_info)
ISZERO %jumpi(sstore_sclear)
%jump(sstore_no_refund)
sstore_sclear:
PUSH @REFUND_SCLEAR %refund_gas
%jump(sstore_no_refund)
sstore_no_refund:
%stack (current_value, value, original_value, slot, kexit_info) -> (kexit_info, current_value, slot, value)
sstore_after_refund:
// stack: kexit_info, current_value, slot, value
// Check if `value` is equal to `current_value`, and if so exit the kernel early.
%stack (kexit_info, current_value, slot, value) -> (value, current_value, slot, value, kexit_info)
EQ %jumpi(sstore_noop)

View File

@ -32,6 +32,10 @@ pub fn evm_constants() -> HashMap<String, U256> {
c.insert(name.into(), U256::from(value));
}
for (name, value) in REFUND_CONSTANTS {
c.insert(name.into(), U256::from(value));
}
for (name, value) in PRECOMPILES {
c.insert(name.into(), U256::from(value));
}
@ -175,7 +179,7 @@ const EC_CONSTANTS: [(&str, [u8; 32]); 20] = [
),
];
const GAS_CONSTANTS: [(&str, u16); 38] = [
const GAS_CONSTANTS: [(&str, u16); 36] = [
("GAS_ZERO", 0),
("GAS_JUMPDEST", 1),
("GAS_BASE", 2),
@ -192,8 +196,6 @@ const GAS_CONSTANTS: [(&str, u16); 38] = [
("GAS_COLDSLOAD_MINUS_WARMACCESS", 2_000),
("GAS_SSET", 20_000),
("GAS_SRESET", 2_900),
("REFUND_SCLEAR", 15_000),
("REFUND_SELFDESTRUCT", 24_000),
("GAS_SELFDESTRUCT", 5_000),
("GAS_CREATE", 32_000),
("GAS_CODEDEPOSIT", 200),
@ -216,6 +218,8 @@ const GAS_CONSTANTS: [(&str, u16); 38] = [
("GAS_BLOCKHASH", 20),
];
const REFUND_CONSTANTS: [(&str, u16); 2] = [("REFUND_SCLEAR", 4_800), ("MAX_REFUND_QUOTIENT", 5)];
const PRECOMPILES: [(&str, u16); 9] = [
("ECREC", 1),
("SHA256", 2),