Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use intcblock, bytecblock information for intc*, bytec* instructions #127

Merged
merged 6 commits into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .github/workflows/pytest310.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
- name: Run detectors tests in 3.10
run: |
pytest tests/test_detectors.py
pytest tests/test_detectors_using_pyteal.py

- name: Run dataflow analysis tests in 3.10
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
build/
dist/
tealer.egg-info/
__pycache__
8 changes: 6 additions & 2 deletions tealer/detectors/can_close_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)
from tealer.teal.basic_blocks import BasicBlock
from tealer.detectors.utils import detect_missing_tx_field_validations

from tealer.utils.teal_enums import TealerTransactionType

if TYPE_CHECKING:
from tealer.utils.output import SupportedOutput
Expand Down Expand Up @@ -74,7 +74,11 @@ def detect(self) -> "SupportedOutput":
def checks_field(block_ctx: "BlockTransactionContext") -> bool:
# return False if CloseRemainderTo field can have any address.
# return True if CloseRemainderTo should have some address or zero address
return not block_ctx.closeto.any_addr
# CloseRemainderTo field can only be set for Payment type transactions.
return not (
block_ctx.closeto.any_addr
and TealerTransactionType.Pay in block_ctx.transaction_types
)

paths_without_check: List[List[BasicBlock]] = detect_missing_tx_field_validations(
self.teal.bbs[0], checks_field
Expand Down
7 changes: 6 additions & 1 deletion tealer/detectors/can_close_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
)
from tealer.teal.basic_blocks import BasicBlock
from tealer.detectors.utils import detect_missing_tx_field_validations
from tealer.utils.teal_enums import TealerTransactionType

if TYPE_CHECKING:
from tealer.utils.output import SupportedOutput
Expand Down Expand Up @@ -69,7 +70,11 @@ def detect(self) -> "SupportedOutput":
def checks_field(block_ctx: "BlockTransactionContext") -> bool:
# return False if AssetCloseTo field can have any address.
# return True if AssetCloseTo should have some address or zero address
return not block_ctx.assetcloseto.any_addr
# AssetCloseTo field can only be set for Asset Transafer type transactions.
return not (
block_ctx.assetcloseto.any_addr
and TealerTransactionType.Axfer in block_ctx.transaction_types
)

paths_without_check: List[List[BasicBlock]] = detect_missing_tx_field_validations(
self.teal.bbs[0], checks_field
Expand Down
134 changes: 89 additions & 45 deletions tealer/teal/instructions/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4058,8 +4058,28 @@ def __init__(self, int_list: List[int]):
def __str__(self) -> str:
return " ".join(["intcblock"] + list(map(str, self._constants)))

@property
def constants(self) -> List[int]:
return self._constants


class IntcInstruction(Instruction):
"""Base class for Intc, Intc_0, Intc_1, Intc_2, Intc_3"""

def __init__(self) -> None:
super().__init__()
self._idx: int = 0

class Intc(Instruction):
@property
def index(self) -> int:
return self._idx

@property
def stack_push_size(self) -> int:
return 1


class Intc(IntcInstruction):
"""`intc i` push integer constant loaded from constant storage space.

Immediates:
Expand All @@ -4077,76 +4097,88 @@ def __init__(self, idx: int):
def __str__(self) -> str:
return f"intc {self._idx}"

@property
def stack_push_size(self) -> int:
return 1


class Intc0(Instruction):
class Intc0(IntcInstruction):
"""`intc_0` push integer constant 0 from constant storage space.

Pushes:
push constant 0 from intcblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 0

def __str__(self) -> str:
return "intc_0"

@property
def stack_push_size(self) -> int:
return 1


class Intc1(Instruction):
class Intc1(IntcInstruction):
"""`intc_1` push integer constant 1 from constant storage space.

Pushes:
push constant 1 from intcblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 1

def __str__(self) -> str:
return "intc_1"

@property
def stack_push_size(self) -> int:
return 1


class Intc2(Instruction):
class Intc2(IntcInstruction):
"""`intc_2` push integer constant 2 from constant storage space.

Pushes:
push constant 2 from intcblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 2

def __str__(self) -> str:
return "intc_2"

@property
def stack_push_size(self) -> int:
return 1


class Intc3(Instruction):
class Intc3(IntcInstruction):
"""`intc_3` push integer constant 3 from constant storage space.

Pushes:
push constant 3 from intcblock to stack.

"""

@property
def stack_push_size(self) -> int:
return 1
def __init__(self) -> None:
super().__init__()
self._idx = 3

def __str__(self) -> str:
return "intc_3"


class Bytec(Instruction):
class BytecInstruction(Instruction):
"""Base class for Bytec, Bytec_0, Bytec_1, Bytec_2, Bytec_3"""

def __init__(self) -> None:
super().__init__()
self._idx: int = 0

@property
def index(self) -> int:
return self._idx

@property
def stack_push_size(self) -> int:
return 1


class Bytec(BytecInstruction):
"""`bytec i` push byte constant loaded from constant storage space.

Immediates:
Expand All @@ -4161,22 +4193,22 @@ def __init__(self, idx: int):
super().__init__()
self._idx = idx

@property
def stack_push_size(self) -> int:
return 1

def __str__(self) -> str:
return f"bytec {self._idx}"


class Bytec0(Instruction):
class Bytec0(BytecInstruction):
"""`bytec_0` push byte constant 0 from constant storage space.

Pushes:
push constant 0 from bytecblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 0

def __str__(self) -> str:
return "bytec_0"

Expand All @@ -4185,53 +4217,53 @@ def stack_push_size(self) -> int:
return 1


class Bytec1(Instruction):
class Bytec1(BytecInstruction):
"""`bytec_1` push byte constant 1 from constant storage space.

Pushes:
push constant 1 from bytecblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 1

def __str__(self) -> str:
return "bytec_1"

@property
def stack_push_size(self) -> int:
return 1


class Bytec2(Instruction):
class Bytec2(BytecInstruction):
"""`bytec_2` push byte constant 2 from constant storage space.

Pushes:
push constant 2 from bytecblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 2

def __str__(self) -> str:
return "bytec_2"

@property
def stack_push_size(self) -> int:
return 1


class Bytec3(Instruction):
class Bytec3(BytecInstruction):
"""`bytec_3` push byte constant 3 from constant storage space.

Pushes:
push constant 3 from bytecblock to stack.

"""

def __init__(self) -> None:
super().__init__()
self._idx = 3

def __str__(self) -> str:
return "bytec_3"

@property
def stack_push_size(self) -> int:
return 1


class Arg(Instruction):
"""`arg n` pushes n LogicSig argument to stack.
Expand Down Expand Up @@ -4362,6 +4394,10 @@ def __str__(self) -> str:
def stack_push_size(self) -> int:
return 1

@property
def value(self) -> str:
return self._bytes


class PushBytes(Instruction):
"""`pushbytes x` instruction pushes immediate value to the top of the stack.
Expand Down Expand Up @@ -4394,6 +4430,10 @@ def __str__(self) -> str:
def stack_push_size(self) -> int:
return 1

@property
def value(self) -> str:
return self._bytes


class Len(Instruction):
"""`len` calculates the length of the given byte array.
Expand Down Expand Up @@ -4428,6 +4468,10 @@ def __init__(self, bytes_list: List[str]):
super().__init__()
self._constants = bytes_list

@property
def constants(self) -> List[str]:
return self._constants

def __str__(self) -> str:
return " ".join(["bytecblock"] + self._constants)

Expand Down
Loading