Skip to content

Commit

Permalink
Update acct existence check in EVM.SELFDESTRUCT_gas
Browse files Browse the repository at this point in the history
  • Loading branch information
wolflo committed Sep 1, 2020
1 parent fa4d888 commit 23f782d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
2 changes: 1 addition & 1 deletion manticore/platforms/evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2277,7 +2277,7 @@ def SELFDESTRUCT_gas(self, recipient):
CreateBySelfdestructGas = 25000
SelfdestructRefundGas = 24000
fee = 0
if recipient not in self.world and self.world.get_balance(self.address) != 0:
if not self.world.account_exists(recipient) and self.world.get_balance(self.address) != 0:
fee += CreateBySelfdestructGas

if self.address not in self.world._deleted_accounts:
Expand Down
49 changes: 49 additions & 0 deletions tests/ethereum/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,55 @@ def test_call_gas(self):
GCALLSTATIC + GCALLVALUE + GCALLNEW - GCALLSTIPEND
)

def test_selfdestruct_gas(self):
GSDSTATIC = 26003 # 21000 + 3 (push op) + 5000 static cost for selfdestruct
GNEWACCOUNT = 25000
RSELFDESTRUCT = 24000

with disposable_mevm() as m:
# empty call target
empty = m.create_account(address=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
# nonempty call target
nonempty = m.create_account(address=0x1111111111111111111111111111111111111111, nonce=1)

asm_sd_empty = """ PUSH20 0xffffffffffffffffffffffffffffffffffffffff
SELFDESTRUCT
"""
asm_sd_nonempty = """ PUSH20 0x1111111111111111111111111111111111111111
SELFDESTRUCT
"""

caller = m.create_account(
address=0x222222222222222222222222222222222222222, balance=1000000000000000000
)

# selfdestruct to empty acct with no value
sd_empty = m.create_account(code=EVMAsm.assemble(asm_sd_empty))
m.transaction(caller=caller, address=sd_empty, data=b"", value=0, gas=50000000)
self.assertEqual(m.count_ready_states(), 1)
state = next(m.ready_states)
txs = state.platform.transactions
# no value, so only static cost charged and refund is gas_used / 2
self.assertEqual(txs[-1].used_gas, round(GSDSTATIC - (GSDSTATIC / 2)))

# selfdestruct to existing acct with value > 0
sd_nonempty = m.create_account(code=EVMAsm.assemble(asm_sd_nonempty))
m.transaction(caller=caller, address=sd_nonempty, data=b"", value=1, gas=50000000)
self.assertEqual(m.count_ready_states(), 1)
state = next(m.ready_states)
txs = state.platform.transactions
# recipient exists, so only static cost charged and refund is gas_used / 2
self.assertEqual(txs[-1].used_gas, round(GSDSTATIC - (GSDSTATIC / 2)))

# selfdestruct to empty acct with value > 0, forcing addition to state trie
sd_empty = m.create_account(code=EVMAsm.assemble(asm_sd_empty))
m.transaction(caller=caller, address=sd_empty, data=b"", value=1, gas=50000000)
self.assertEqual(m.count_ready_states(), 1)
state = next(m.ready_states)
txs = state.platform.transactions
# new account gas charged and full refund returned
self.assertEqual(txs[-1].used_gas, GSDSTATIC + GNEWACCOUNT - RSELFDESTRUCT)


class EthPluginTests(unittest.TestCase):
def test_FilterFunctions_fallback_function_matching(self):
Expand Down

0 comments on commit 23f782d

Please sign in to comment.