diff --git a/src/env_info.rs b/src/env_info.rs index 88367fca9..9620dd7b8 100644 --- a/src/env_info.rs +++ b/src/env_info.rs @@ -45,7 +45,7 @@ impl EnvInfo { difficulty: u256_from_json(&json["currentDifficulty"]), gas_limit: u256_from_json(&json["currentGasLimit"]), timestamp: u64_from_json(&json["currentTimestamp"]), - last_hashes: (1..257).map(|i| format!("{}", current_number - i).as_bytes().sha3()).collect(), + last_hashes: (0..current_number).map(|i| format!("{}", current_number - i).as_bytes().sha3()).collect(), gas_used: x!(0), } } diff --git a/src/executive.rs b/src/executive.rs index 36ed48a6a..de65e183f 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -219,11 +219,23 @@ impl<'a> Executive<'a> { } /// Finalizes the transaction (does refunds and suicides). - fn finalize(&mut self, t: &Transaction, substate: Substate, backup: State, result: evm::Result) -> ExecutionResult { + fn finalize(&mut self, t: &Transaction, substate: Substate, mut backup: State, result: evm::Result) -> ExecutionResult { match result { Err(evm::Error::Internal) => Err(ExecutionError::Internal), Err(evm::Error::OutOfGas) => { - *self.state = backup; + // apply first transfer to backup, and then revert everything + let sender = t.sender().unwrap(); + match t.action() { + &Action::Create => { + let nonce = backup.nonce(&sender); + let address = contract_address(&sender, &nonce); + backup.new_contract(&address); + backup.transfer_balance(&sender, &address, &t.value); + } + &Action::Call(ref address) => backup.transfer_balance(&sender, address, &t.value) + } + + self.state.revert(backup); Ok(Executed { gas: t.gas, gas_used: t.gas, @@ -832,9 +844,9 @@ mod tests { }; assert_eq!(executed.gas, U256::from(100_000)); - assert_eq!(executed.gas_used, U256::from(20_025)); - assert_eq!(executed.refunded, U256::from(79_975)); - assert_eq!(executed.cumulative_gas_used, U256::from(20_025)); + assert_eq!(executed.gas_used, U256::from(41_301)); + assert_eq!(executed.refunded, U256::from(58_699)); + assert_eq!(executed.cumulative_gas_used, U256::from(41_301)); assert_eq!(executed.logs.len(), 0); assert_eq!(executed.out_of_gas, false); assert_eq!(executed.contracts_created.len(), 0); diff --git a/src/state.rs b/src/state.rs index 1f58f638c..fc7ffdb4c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -138,10 +138,15 @@ impl State { /// This will change the state accordingly. pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult { let e = try!(Executive::new(self, env_info, engine).transact(t)); + println!("Executed: {:?}", e); self.commit(); Ok(Receipt::new(self.root().clone(), e.gas_used, e.logs)) } + pub fn revert(&mut self, backup: State) { + self.cache = backup.cache; + } + /// Convert into a JSON representation. pub fn as_json(&self) -> String { unimplemented!(); diff --git a/src/tests/state.rs b/src/tests/state.rs index 080bdf979..10ad3a657 100644 --- a/src/tests/state.rs +++ b/src/tests/state.rs @@ -57,4 +57,4 @@ fn do_json_test(json_data: &[u8]) -> Vec { } declare_test!{StateTests_stExample, "StateTests/stExample"} -declare_test!{StateTests_stLogTests, "StateTests/stLogTests"} \ No newline at end of file +declare_test!{StateTests_stLogTests, "StateTests/stLogTests"}