StateAccessViolation: Value must be a literal - Vyper 以太坊智能合约
StateAccessViolation: Value must be a literal - Vyper Ethereum smart contract
版本信息
- vyper 版本(
vyper --version
的输出):0.2.8+commit.069936f
- OS: 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-函数的描述,只有一种方法可以将变量传递给它:
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 循环的原因是为了确保当 'employee' 是 'fired' 或 'quit' 时 [=列表中不会有空记录 'employee'正在维护
相反,为了避免完全使用 for 循环,并以无法删除不再“活跃的员工”为代价,最佳做法是仅在哈希图中跟踪 'employee':
idToEmployee: HashMap[uint256, employee]
并且在跟踪员工时,只需使用名为 num_employees
的全局变量将 id
属性分配给 'employee'
例如:
def employ():
new_employee: employee = employee ({
id: self.num_employees
})
self.idToEmployee[self.num_employees] = new_employee
尝试查看或更新该员工的信息时,只需使用:
self.idToEmployee[id]
@vladimir 很好地解释了范围是如何传递变量的,如果仍然对 reader
的 vyper 中的 for
循环感到困惑的话
版本信息
- vyper 版本(
vyper --version
的输出):0.2.8+commit.069936f - OS: 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-函数的描述,只有一种方法可以将变量传递给它:
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 循环的原因是为了确保当 'employee' 是 'fired' 或 'quit' 时 [=列表中不会有空记录 'employee'正在维护
相反,为了避免完全使用 for 循环,并以无法删除不再“活跃的员工”为代价,最佳做法是仅在哈希图中跟踪 'employee':
idToEmployee: HashMap[uint256, employee]
并且在跟踪员工时,只需使用名为 num_employees
id
属性分配给 'employee'
例如:
def employ():
new_employee: employee = employee ({
id: self.num_employees
})
self.idToEmployee[self.num_employees] = new_employee
尝试查看或更新该员工的信息时,只需使用:
self.idToEmployee[id]
@vladimir 很好地解释了范围是如何传递变量的,如果仍然对 reader
的 vyper 中的for
循环感到困惑的话