StateAccessViolation:值必须是文字 - Vyper Ethereum 智能合约 版本信息

问题描述

版本信息

  • vyper 版本(vyper --version输出):0.2.8+commit.069936f
  • 操作系统:osx
  • Python 版本(python --version输出):Python 2.7.16
  • 环境(pip freeze输出):
altgraph==0.10.2
bdist-mpkg==0.5.0
bonjour-py==0.3
macholib==1.5.1
matplotlib==1.3.1
modulegraph==0.10.4
numpy==1.8.0rc1
py2app==0.7.3
pyobjc-core==2.5.1
pyobjc-framework-Accounts==2.5.1
pyobjc-framework-AddressBook==2.5.1
pyobjc-framework-AppleScriptKit==2.5.1
pyobjc-framework-AppleScriptObjC==2.5.1
pyobjc-framework-Automator==2.5.1
pyobjc-framework-CFNetwork==2.5.1
pyobjc-framework-Cocoa==2.5.1
pyobjc-framework-Collaboration==2.5.1
pyobjc-framework-CoreData==2.5.1
pyobjc-framework-CoreLocation==2.5.1
pyobjc-framework-CoreText==2.5.1
pyobjc-framework-DictionaryServices==2.5.1
pyobjc-framework-EventKit==2.5.1
pyobjc-framework-ExceptionHandling==2.5.1
pyobjc-framework-FSEvents==2.5.1
pyobjc-framework-InputMethodKit==2.5.1
pyobjc-framework-InstallerPlugins==2.5.1
pyobjc-framework-InstantMessage==2.5.1
pyobjc-framework-LatentSemanticMapping==2.5.1
pyobjc-framework-LaunchServices==2.5.1
pyobjc-framework-Message==2.5.1
pyobjc-framework-OpenDirectory==2.5.1
pyobjc-framework-PreferencePanes==2.5.1
pyobjc-framework-PubSub==2.5.1
pyobjc-framework-QTKit==2.5.1
pyobjc-framework-Quartz==2.5.1
pyobjc-framework-ScreenSaver==2.5.1
pyobjc-framework-ScriptingBridge==2.5.1
pyobjc-framework-SearchKit==2.5.1
pyobjc-framework-ServiceManagement==2.5.1
pyobjc-framework-Social==2.5.1
pyobjc-framework-SyncServices==2.5.1
pyobjc-framework-SystemConfiguration==2.5.1
pyobjc-framework-WebKit==2.5.1
pyOpenSSL==0.13.1
pyparsing==2.0.1
python-dateutil==1.5
pytz==2013.7
scipy==0.13.0b1
six==1.4.1
xattr==0.6.4

for 循环调用

for i in range(self.some_uint256):
      # do something...

正在抛出错误StateAccessViolation: Value must be a literal

完整的错误输出

vyper.exceptions.StateAccessViolation: Value must be a literalvyper.exceptions.StateAccessViolation: Value must be a literal
contract "vyper-farm/contracts/Farm.vy",function "_employ",line 152:4
151
---> 152 for i in range(self.num_employees):
-------------^
153 pass

我到底做错了什么?

这是对我的字面意思的误解吗?

解决方法

看一下range-function的描述,只有一种方法可以给它传递一个变量:

for i in range(a,a + N):
    pass

在你的情况下它应该是这样的(不确定它是否有用):

num_employees: public(uint256)

@external
def __init__():
    self.num_employees = 16

@external
def do_smth():
    for i in range(self.num_employees,self.num_employees + 10):
        pass
,

上述问题不是对for循环使用的误解,而是编码风格与vyper的安全措施不兼容的结果

创建 for 循环的原因是为了确保“员工”何时被“解雇”或“退出”,那么正在维护的“员工”列表中不会有空记录

相反,为了避免完全使用 for 循环,并且为了不能删除不再是“活跃员工”的小牺牲,最佳做法是仅在哈希图中跟踪“员工”:

idToEmployee: HashMap[uint256,employee]

并且在跟踪员工时,只需使用名为 id 的全局变量将 num_employees 属性分配给“员工”

例如:

def employ():
   new_employee: employee = employee ({
        id: self.num_employees
   })

   self.idToEmployee[self.num_employees] = new_employee

尝试查看或更新该员工的信息时,只需使用:

self.idToEmployee[id]

@vladimir 很好地解释了如果读者仍然对 vyper 中的 for 循环感到困惑,范围是如何传递变量的

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...