Add BASEFEE opcode (#1513)

* Add BASEFEE opcode

* Add test
pull/1518/head
Nikhil Parasaram 3 years ago committed by GitHub
parent cf5f2dd5e0
commit 067d2c0b47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      mythril/laser/ethereum/instruction_data.py
  2. 10
      mythril/laser/ethereum/instructions.py
  3. 2
      mythril/laser/ethereum/state/environment.py
  4. 32
      mythril/laser/ethereum/transaction/transaction_models.py
  5. 1
      mythril/support/opcodes.py
  6. 2
      tests/instructions/berlin_fork_opcodes_test.py
  7. 2
      tests/instructions/codecopy_test.py
  8. 2
      tests/instructions/create2_test.py
  9. 2
      tests/instructions/create_test.py
  10. 4
      tests/instructions/extcodecopy_test.py
  11. 2
      tests/instructions/extcodehash_test.py
  12. 2
      tests/instructions/sar_test.py
  13. 2
      tests/instructions/shl_test.py
  14. 2
      tests/instructions/shr_test.py
  15. 2
      tests/instructions/static_call_test.py
  16. 39
      tests/instructions/test_basefee.py

@ -175,6 +175,7 @@ OPCODES = {
"CALL": {GAS: (700, 700 + 9000 + 25000), STACK: (7, 1)},
"CALLCODE": {GAS: (700, 700 + 9000 + 25000), STACK: (7, 1)},
"RETURN": {GAS: (0, 0), STACK: (2, 0)},
"BASEFEE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE},
"DELEGATECALL": {GAS: (700, 700 + 9000 + 25000), STACK: (6, 1)},
"STATICCALL": {GAS: (700, 700 + 9000 + 25000), STACK: (6, 1)},
"REVERT": {GAS: (0, 0), STACK: (2, 0)},

@ -1041,6 +1041,16 @@ class Instruction:
global_state.mstate.stack.append(global_state.environment.gasprice)
return [global_state]
@StateTransition()
def basefee_(self, global_state: GlobalState) -> List[GlobalState]:
"""
:param global_state:
:return:
"""
global_state.mstate.stack.append(global_state.environment.basefee)
return [global_state]
@StateTransition()
def codecopy_(self, global_state: GlobalState) -> List[GlobalState]:
"""

@ -21,6 +21,7 @@ class Environment:
gasprice: ExprRef,
callvalue: ExprRef,
origin: ExprRef,
basefee: ExprRef,
code=None,
static=False,
) -> None:
@ -55,6 +56,7 @@ class Environment:
self.origin = origin
self.callvalue = callvalue
self.static = static
self.basefee = basefee
def __str__(self) -> str:
"""

@ -69,6 +69,7 @@ class BaseTransaction:
call_value=None,
init_call_data=True,
static=False,
base_fee=None,
) -> None:
assert isinstance(world_state, WorldState)
self.world_state = world_state
@ -77,14 +78,21 @@ class BaseTransaction:
self.gas_price = (
gas_price
if gas_price is not None
else symbol_factory.BitVecSym("gasprice{}".format(identifier), 256)
else symbol_factory.BitVecSym(f"gasprice{identifier}", 256)
)
self.base_fee = (
base_fee
if base_fee is not None
else symbol_factory.BitVecSym(f"basefee{identifier}", 256)
)
self.gas_limit = gas_limit
self.origin = (
origin
if origin is not None
else symbol_factory.BitVecSym("origin{}".format(identifier), 256)
else symbol_factory.BitVecSym(f"origin{identifier}", 256)
)
self.code = code
@ -102,7 +110,7 @@ class BaseTransaction:
self.call_value = (
call_value
if call_value is not None
else symbol_factory.BitVecSym("callvalue{}".format(identifier), 256)
else symbol_factory.BitVecSym(f"callvalue{identifier}", 256)
)
self.static = static
self.return_data = None # type: str
@ -161,6 +169,7 @@ class MessageCallTransaction(BaseTransaction):
self.gas_price,
self.call_value,
self.origin,
self.base_fee,
code=self.code or self.callee_account.code,
static=self.static,
)
@ -196,6 +205,7 @@ class ContractCreationTransaction(BaseTransaction):
call_value=None,
contract_name=None,
contract_address=None,
base_fee=None,
) -> None:
self.prev_world_state = deepcopy(world_state)
contract_address = (
@ -219,18 +229,20 @@ class ContractCreationTransaction(BaseTransaction):
code=code,
call_value=call_value,
init_call_data=True,
base_fee=base_fee,
)
def initial_global_state(self) -> GlobalState:
"""Initialize the execution environment."""
environment = Environment(
self.callee_account,
self.caller,
self.call_data,
self.gas_price,
self.call_value,
self.origin,
self.code,
active_account=self.callee_account,
sender=self.caller,
calldata=self.call_data,
gasprice=self.gas_price,
callvalue=self.call_value,
origin=self.origin,
basefee=self.base_fee,
code=self.code,
)
return super().initial_global_state_from_environment(
environment, active_function="constructor"

@ -53,6 +53,7 @@ opcodes = {
0x45: ("GASLIMIT", 0, 1, 2),
0x46: ("CHAINID", 0, 1, 2),
0x47: ("SELFBALANCE", 0, 1, 5),
0x48: ("BASEFEE", 0, 1, 2),
0x50: ("POP", 1, 0, 2),
0x51: ("MLOAD", 1, 1, 3),
0x52: ("MSTORE", 2, 0, 3),

@ -17,7 +17,7 @@ def get_state():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("0x60045e005c5d")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)

@ -13,7 +13,7 @@ def test_codecopy_concrete():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
og_state = GlobalState(
world_state, environment, None, MachineState(gas_limit=8000000)
)

@ -34,7 +34,7 @@ def test_create2():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
og_state = GlobalState(
world_state, environment, None, MachineState(gas_limit=8000000)
)

@ -21,7 +21,7 @@ def test_create():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606060")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
og_state = GlobalState(
world_state, environment, None, MachineState(gas_limit=8000000)
)

@ -16,7 +16,7 @@ def test_extcodecopy():
ext_account = new_world_state.create_account(balance=1000, address=121)
ext_account.code = Disassembly("6040404040")
new_environment = Environment(new_account, None, None, None, None, None)
new_environment = Environment(new_account, None, None, None, None, None, None)
state = GlobalState(
new_world_state, new_environment, None, MachineState(gas_limit=8000000)
)
@ -38,7 +38,7 @@ def test_extcodecopy_fail():
new_world_state = WorldState()
new_account = new_world_state.create_account(balance=10, address=101)
new_account.code = Disassembly("60616240")
new_environment = Environment(new_account, None, None, None, None, None)
new_environment = Environment(new_account, None, None, None, None, None, None)
state = GlobalState(
new_world_state, new_environment, None, MachineState(gas_limit=8000000)
)

@ -16,7 +16,7 @@ world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
world_state.create_account(balance=10, address=1000)
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
og_state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000))
og_state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)

@ -16,7 +16,7 @@ def get_state():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)

@ -15,7 +15,7 @@ def get_state():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)

@ -15,7 +15,7 @@ def get_state():
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
environment = Environment(account, None, None, None, None, None)
environment = Environment(account, None, None, None, None, None, None)
state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)

@ -19,7 +19,7 @@ from mythril.laser.ethereum.evm_exceptions import WriteProtection
def get_global_state():
active_account = Account("0x0", code=Disassembly("60606040"))
environment = Environment(
active_account, None, SymbolicCalldata("2"), None, None, None
active_account, None, SymbolicCalldata("2"), None, None, None, None
)
world_state = WorldState()
world_state.put_account(active_account)

@ -0,0 +1,39 @@
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction
from mythril.laser.smt import symbol_factory
def test_basefee():
# Arrange
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
environment = Environment(
account,
None,
None,
None,
None,
None,
basefee=symbol_factory.BitVecSym("gasfee", 256),
)
og_state = GlobalState(
world_state, environment, None, MachineState(gas_limit=8000000)
)
og_state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
)
og_state.mstate.stack = []
instruction = Instruction("basefee", dynamic_loader=None)
# Act
new_state = instruction.evaluate(og_state)[0]
# Assert
assert new_state.mstate.stack == [symbol_factory.BitVecSym("gasfee", 256)]
Loading…
Cancel
Save