Ton区块链发送消息失败报错exitcode=36,请求技术排查
Ton区块链发送消息报错(Exit Code 36)排查与修复
我在向Ton区块链发送消息时遇到问题,确认代码逻辑无误,但仍报错。以下是我的代码:
async def deposit(self, amount, to_address, comment=None, token=None, fee=0.06): try: wallet = self.import_wallet() seqno = self.get_seqno() if token: token_address = self.client.define_token(**token)[0]["owner_address"] body = JettonWallet().create_transfer_body( to_address=Address(to_address), jetton_amount=amount * 10 ** 9 ) query = wallet.create_transfer_message( to_addr=token_address, seqno=seqno, payload=body, amount=fee * 10 ** 9 )["message"].to_boc(False) else: query = wallet.create_transfer_message( to_addr=to_address, amount=to_nano(amount, "ton"), payload=comment if comment else "no message", seqno=seqno, send_mode=3 )["message"].to_boc(False) client = await self.ton_client.get_client(index=5) await client.raw_send_message(query) return "Deposit successful." except Exception as e: return f"Failed to send deposit: {e}" finally: await client.close()
完整错误信息如下:
{ "response": "Failed to send deposit: LITE_SERVER_UNKNOWN: cannot apply external message to current state : External message was not accepted\nCannot run message on account: inbound external message rejected by transaction 0332CEA4C9A11B46D22461E4C5DB6CDB885DBAEB73C60BB00F71C200D5C21E29:\nexitcode=36, steps=13, gas_used=0\nVM Log (truncated):\n...CTPUSHCONST 19 (xC_,1)\nexecute DICTIGETJMPZ\nexecute PUSHPOW2 9\nexecute LDSLICEX\nexecute DUP\nexecute LDU 32\nexecute LDU 32\nexecute LDU 32\nexecute XCHG s2\nexecute NOW\nexecute LEQ\nexecute THROWIF 36\ndefault exception handler, terminating vm with exit code 36\n" }
问题分析
Exit Code 36对应消息过期,Ton钱包合约会校验消息的expire_at字段,若当前链上时间超过该值,就会拒绝执行消息。从VM日志里的NOW、LEQ、THROWIF 36也能验证这一点——合约在对比当前时间与消息过期时间,发现已过期后抛出异常。
修复方案
1. 显式设置消息过期时间
创建转账消息时添加expire_at参数,设置合理的过期时间(比如当前时间+300秒,即5分钟),避免消息因网络延迟或链上拥堵过期。修改后的代码如下:
import time import asyncio async def deposit(self, amount, to_address, comment=None, token=None, fee=0.06): try: wallet = self.import_wallet() seqno = self.get_seqno() # 设置过期时间:当前时间 + 300秒(5分钟) expire_at = int(time.time()) + 300 if token: token_address = self.client.define_token(**token)[0]["owner_address"] body = JettonWallet().create_transfer_body( to_address=Address(to_address), jetton_amount=amount * 10 ** 9 ) query = wallet.create_transfer_message( to_addr=token_address, seqno=seqno, payload=body, amount=fee * 10 ** 9, expire_at=expire_at # 添加过期时间 )["message"].to_boc(False) else: query = wallet.create_transfer_message( to_addr=to_address, amount=to_nano(amount, "ton"), payload=comment if comment else "no message", seqno=seqno, send_mode=3, expire_at=expire_at # 添加过期时间 )["message"].to_boc(False) client = await self.ton_client.get_client(index=5) await client.raw_send_message(query) return "Deposit successful." except Exception as e: return f"Failed to send deposit: {e}" finally: await client.close()
2. 确保seqno实时性
获取seqno后,确保其为最新值,避免使用过时seqno导致消息被拒。可添加短暂延迟或重试时重新获取:
seqno = self.get_seqno() # 可选:添加短延迟确保seqno同步 await asyncio.sleep(0.5)
3. 检查send_mode参数
当前使用send_mode=3(SEND_MODE_PAY_GAS_SEPARATELY),普通转账没问题,但Jetton转账需确认合约支持该模式。若有问题,可尝试改为send_mode=128(SEND_MODE_DESTROY_IF_ZERO)或其他合适模式。
内容的提问来源于stack exchange,提问作者pouya Chraghchian
相关产品推荐
相关产品推荐

