如何在Python中向Starknet合约正确传递长字符串?
解决Starknet合约传递长字符串的问题
错误原因
你遇到的"Input too long for arguments"错误,本质是Starknet的calldata每个参数都是Felt(252位字段元素),单个Felt最多只能存储31字节的数据,直接传递长字符串会超出单个参数的长度限制。必须将长字符串编码为多个Felt组成的数组,再作为calldata传递。
解决方法
1. 实现字符串转Felt数组的工具函数
将字符串按31字节拆分,每个字节块转换为对应的Felt数值:
def string_to_felt_array(s: str) -> list[int]: bytes_data = s.encode("utf-8") felts = [] for i in range(0, len(bytes_data), 31): chunk = bytes_data[i:i+31] felt = int.from_bytes(chunk, byteorder="big") felts.append(felt) return felts
2. 修改调用代码
先修正原字符串的语法错误("op":"min"改为"op":"mint",移除多余的"t",),再用工具函数转换为Felt数组作为calldata:
async with aiohttp.TCPConnector(ssl=False) as tcpconnector: async with aiohttp.ClientSession(connector=tcpconnector,trust_env=True) as session: full_node_client = FullNodeClient(node_url=node_url,session=session) account = Account( client=full_node_client, address=address, key_pair=KeyPair.from_private_key(key=private_key), chain=StarknetChainId.MAINNET, ) # 修正后的目标数据字符串 inscribe_str = 'data:,{"p":"stark-20","op":"mint","tick":"STRK","amt":"1000"}' # 转换为Felt数组作为calldata calldata = string_to_felt_array(inscribe_str) call = Call( to_addr=0x07341189e3c96f636a4192cfba8c18deeee33a19c5d0425a26cf96ea42388c4e, selector=get_selector_from_name("inscribe"), calldata=calldata ) calls = [call] tx = await account.sign_invoke_transaction( calls=calls, max_fee=0 ) estimated_fee = await account.client.estimate_fee( tx=tx, )
注意事项
- 确保目标合约的
inscribe函数参数类型为felt[],否则无法接收拆分后的Felt数组。如果合约定义的是单个felt,需要确认合约是否支持先传递字符串长度、再传递拆分后的Felt序列的方式。 - 按31字节拆分是因为Felt的最大有效存储长度为31字节(252位=31.5字节,取整避免溢出)。
内容的提问来源于stack exchange,提问作者unix55
相关产品推荐
相关产品推荐

