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

vyper.exceptions.StackTooDeep: Unsupported dup depth 17 #4222

Open
xrchz opened this issue Sep 2, 2024 · 2 comments
Open

vyper.exceptions.StackTooDeep: Unsupported dup depth 17 #4222

xrchz opened this issue Sep 2, 2024 · 2 comments
Labels
bug - venom bug in experimental venom pipeline

Comments

@xrchz
Copy link
Contributor

xrchz commented Sep 2, 2024

Version Information

  • vyper Version (output of vyper --version): 0.4.0+commit.e9db8d9
  • OS: GNU/Linux
  • Python Version (output of python --version): Python 3.12.5

What's your issue about?

I ran
vyper --verbose bug.vy

where bug.vy contains

#pragma version ~=0.4.0
#pragma evm-version cancun
#pragma optimize gas
#pragma experimental-codegen

MAX_CLAIM_INTERVALS: constant(uint256) = 128 # ~10 years
MAX_PROOF_LENGTH: constant(uint256) = 32 # ~ 4 billion claimers

interface RocketStorageInterface:
  def getAddress(_key: bytes32) -> address: view

interface RocketMerkleDistributorInterface:
  def claimAndStake(_nodeAddress: address,
            _rewardIndex: DynArray[uint256, MAX_CLAIM_INTERVALS],
            _amountRPL: DynArray[uint256, MAX_CLAIM_INTERVALS],
            _amountETH: DynArray[uint256, MAX_CLAIM_INTERVALS],
            _merkleProof: DynArray[DynArray[bytes32, MAX_PROOF_LENGTH], MAX_CLAIM_INTERVALS],
            _stakeAmount: uint256): nonpayable
rocketMerkleDistributorKey: constant(bytes32) = keccak256("contract.addressrocketMerkleDistributorMainnet")

rocketStorage: public(immutable(RocketStorageInterface))

@internal
@view
def _getMerkleDistributor() -> RocketMerkleDistributorInterface:
  return RocketMerkleDistributorInterface(
    staticcall rocketStorage.getAddress(rocketMerkleDistributorKey)
  )

struct BorrowerState:
  RPL: uint256 # RPL available for repayments and/or withdrawal
  ETH: uint256 # ETH available for liquidation and/or withdrawal
  index: uint256 # first not-yet-accounted interval index
  address: address # current address for the borrower

borrowers: public(HashMap[address, BorrowerState])

@deploy
def __init__(_rocketStorage: address):
  rocketStorage = RocketStorageInterface(_rocketStorage)

@external
def forceClaimMerkleRewards(
      _node: address,
      _rewardIndex: DynArray[uint256, MAX_CLAIM_INTERVALS],
      _amountRPL: DynArray[uint256, MAX_CLAIM_INTERVALS],
      _amountETH: DynArray[uint256, MAX_CLAIM_INTERVALS],
      _merkleProof: DynArray[DynArray[bytes32, MAX_PROOF_LENGTH], MAX_CLAIM_INTERVALS]
    ):
  self._claimMerkleRewards(_node, _rewardIndex, _amountRPL, _amountETH, _merkleProof)

@internal
def _updateIndex(_toIndex: uint256):
  pass

@internal
def _claimMerkleRewards(
      _node: address,
      _rewardIndex: DynArray[uint256, MAX_CLAIM_INTERVALS],
      _amountRPL: DynArray[uint256, MAX_CLAIM_INTERVALS],
      _amountETH: DynArray[uint256, MAX_CLAIM_INTERVALS],
      _merkleProof: DynArray[DynArray[bytes32, MAX_PROOF_LENGTH], MAX_CLAIM_INTERVALS],
    ) -> (uint256, uint256):
  maxUnclaimedIndex: uint256 = 0
  totalRPL: uint256 = self.borrowers[_node].RPL
  totalETH: uint256 = self.borrowers[_node].ETH
  for index: uint256 in _rewardIndex:
    maxUnclaimedIndex = max(index + 1, maxUnclaimedIndex)
  extcall self._getMerkleDistributor().claimAndStake(_node, _rewardIndex, _amountRPL, _amountETH, _merkleProof, 0)
  self._updateIndex(maxUnclaimedIndex)
  return totalRPL, totalETH

I got this output

cli specified: `Settings(compiler_version=None, optimize=None, evm_version=None, experimental_codegen=None, debug=None, enable_decimals=None)`
Error compiling: bug.vy
Traceback (most recent call last):
  File "/home/ramana/.local/bin/vyper", line 8, in <module>
    sys.exit(_parse_cli_args())
             ^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/cli/vyper_compile.py", line 65, in _parse_cli_args
    return _parse_args(sys.argv[1:])
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/cli/vyper_compile.py", line 238, in _parse_args
    compiled = compile_files(
               ^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/cli/vyper_compile.py", line 377, in compile_files
    output = vyper.compile_from_file_input(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/compiler/__init__.py", line 129, in compile_from_file_input
    exc_handler(str(file_input.path), exc)
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/cli/vyper_compile.py", line 278, in exc_handler
    raise exception
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/compiler/__init__.py", line 126, in compile_from_file_input
    ret[output_format] = formatter(compiler_data)
                         ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/compiler/output.py", line 367, in build_bytecode_output
    return f"0x{compiler_data.bytecode.hex()}"
                ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/functools.py", line 993, in __get__
    val = self.func(instance)
          ^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/compiler/phases.py", line 253, in bytecode
    return generate_bytecode(self.assembly, insert_compiler_metadata=insert_compiler_metadata)
                             ^^^^^^^^^^^^^
  File "/usr/lib/python3.12/functools.py", line 993, in __get__
    val = self.func(instance)
          ^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/compiler/phases.py", line 235, in assembly
    return generate_assembly_experimental(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/__init__.py", line 39, in generate_assembly_experimental
    return compiler.generate_evm(optimize == OptimizationLevel.NONE)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 160, in generate_evm
    self._generate_evm_for_basicblock_r(asm, fn.entry, StackModel())
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 302, in _generate_evm_for_basicblock_r
    self._generate_evm_for_basicblock_r(asm, bb, stack.copy())
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 302, in _generate_evm_for_basicblock_r
    self._generate_evm_for_basicblock_r(asm, bb, stack.copy())
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 302, in _generate_evm_for_basicblock_r
    self._generate_evm_for_basicblock_r(asm, bb, stack.copy())
  [Previous line repeated 9 more times]
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 299, in _generate_evm_for_basicblock_r
    asm.extend(self._generate_evm_for_instruction(inst, stack, next_liveness))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 405, in _generate_evm_for_instruction
    self._emit_input_operands(assembly, inst, operands, stack)
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 268, in _emit_input_operands
    self.dup_op(assembly, stack, op)
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 571, in dup_op
    self.dup(assembly, stack, stack.get_depth(op))
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 565, in dup
    assembly.append(_evm_dup_for(depth))
                    ^^^^^^^^^^^^^^^^^^^
  File "/home/ramana/.local/pipx/venvs/vyper/lib/python3.12/site-packages/vyper/venom/venom_to_assembly.py", line 584, in _evm_dup_for
    raise StackTooDeep(f"Unsupported dup depth {dup_idx}")
vyper.exceptions.StackTooDeep: Unsupported dup depth 17

This is an unhandled internal compiler error. Please create an issue on Github to notify the developers!
https://github.com/vyperlang/vyper/issues/new?template=bug.md

How can it be fixed?

Fill this in if you know how to fix it.

@xrchz
Copy link
Contributor Author

xrchz commented Sep 2, 2024

More minimised version of bug.vy:

#pragma version ~=0.4.0
#pragma evm-version cancun
#pragma optimize gas
#pragma experimental-codegen

interface Iface:
  def f5(x: DynArray[uint256, 128],
         y: DynArray[DynArray[bytes32, 32], 128]): nonpayable

@internal
@view
def f4() -> Iface:
  return Iface(0x0000000000000000000100000000000000000001)

struct St:
  a: uint256
  b: uint256

s1: public(HashMap[uint256, St])

@external
def f1(x: DynArray[uint256, 128], y: DynArray[DynArray[bytes32, 32], 128]):
  self.f2(x, y)

@internal
def f3(i: uint256):
  pass

@internal
def f2(x: DynArray[uint256, 128], y: DynArray[DynArray[bytes32, 32], 128]) -> (uint256, uint256):
  c: uint256 = 0
  a: uint256 = self.s1[0].a
  b: uint256 = self.s1[0].b
  for i: uint256 in [0]:
    c = i
  extcall self.f4().f5(x, y)
  self.f3(c)
  return a, b

@charles-cooper charles-cooper added the bug - venom bug in experimental venom pipeline label Sep 5, 2024
@charles-cooper
Copy link
Member

we need to add a stack2mem pass in the case where we allocate too many stack variables

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug - venom bug in experimental venom pipeline
Projects
None yet
Development

No branches or pull requests

2 participants