OUT_OF_ENERGY: error TRON yang menghabiskan biaya dan tidak mengirim apa pun
Sebuah transfer USDT berangkat, dompetnya menunjukkan biaya sudah terpotong, dan penerimanya tidak mendapat apa-apa. Transaksinya ada di dalam blok — ia tidak ditolak dan tidak ada node yang mati — dan di tempat transfer yang selesai tertulis SUCCESS, yang ini tertulis OUT_OF_ENERGY. Di TRON error itu berarti persis seperti bunyinya: panggilannya kehabisan energi di tengah jalan lalu berhenti. Inilah mekanismenya, tiga cara satu putaran pembayaran tersandung ke dalamnya, dan perbaikannya, dari yang paling cepat sampai yang benar-benar paling murah.
Apa yang sebenarnya dikatakan hasil itu
Mengirim USDT adalah panggilan ke dalam sebuah kontrak pintar, dan eksekusi kontrak di TRON diukur dalam energi alih-alih ditagih sebagai biaya tetap (apa itu energi). Energi milik pengirim sendiri terpakai lebih dulu. Ketika energi itu tidak menutup panggilannya, jaringan tidak berhenti di situ — ia membeli sisanya dengan membakar TRX milik pengirim pada tarif protokol 100 sun untuk tiap unit, tetapi hanya sejauh yang diizinkan fee_limit transaksi itu sendiri. Field itu bukan biaya yang ditagih siapa pun. Ia plafon atas seberapa banyak TRX pengirim yang boleh dibakar oleh satu panggilan ini.
Sampai di plafon itu dengan panggilan yang belum selesai, eksekusinya berhenti. Tiap perubahan keadaan yang sudah dibuatnya digulung balik, jadi tidak ada token yang berpindah, dan jaringan menuliskan vonisnya pada transaksi itu di tempat panggilan yang selesai membawa SUCCESS. Vonis itulah kata yang ditampilkan explorer di sebelah transaksi yang gagal, dan field yang dikembalikan node sebagai contractRet. Tidak ada bagian transaksi itu yang gagal sampai ke jaringan. Ia sampai ke jaringan dan dijalankan sampai uang untuk menjalankannya habis.
TRX-nya habis, jalan mana pun yang ditempuh
Penggulungan itu membatalkan transfernya. Ia tidak membatalkan pembakarannya: energi yang terpakai adalah energi yang dibayar, dan pengirimnya berkurang sebanyak apa pun yang dibakar percobaan itu dalam perjalanannya menuju plafon, tanpa satu token pun berpindah, dan dengan hash transaksi yang akan dengan senang hati dicatat oleh skrip rekonsiliasi sebagai pembayaran.
Itulah yang membuat percobaan ulang secara refleks menjadi langkah yang mahal. Transfer yang sama dengan batas yang sama menghabiskan TRX yang sama untuk hasil yang sama, dan loop pembayaran yang mengulang kegagalannya secara otomatis bisa melakukannya beberapa kali sebelum ada manusia yang membaca string hasilnya. Sebagian besar kegagalan yang ditemui tim pembayaran memakan uang dengan diam-diam. Yang satu ini memakan uang dengan berisik dan tetap saja terlewat, karena dompetnya melaporkan ada biaya dan uangnya tidak ada di mana-mana.
Kenapa batas yang kemarin bekerja berhenti bekerja
Penerimanya berubah dan batasnya tidak. Inilah yang paling dulu ditemui satu putaran pembayaran. Transfer ke alamat yang sudah memegang USDT memakan sekitar 65,000 unit energi; ke alamat yang belum pernah memegangnya, transfernya harus sekalian membuat akun token milik penerima, dan itu sekitar 131,000 — dua kali lipat seleranya untuk jumlah uang yang sama persis. Membakar untuk yang pertama berharga 6.5 TRX pada tarif protokol, dan untuk yang kedua 13.1 TRX. Plafon yang diukur pada kasus biasa akan kurang separuh pada kali pertama seorang pelanggan baru dibayar, dan tidak ada apa pun dalam kiriman itu yang tampak berbeda: ini sifat penerimanya, bukan sifat transfernya.
Energinya tadi ada dan sekarang tidak lagi. Delegasi adalah sejumlah kuantitas untuk satu jangka, bukan langganan. Yang dihabiskan transfer pertama tidak ada lagi untuk yang kedua, dan ketika jangkanya berakhir sisanya kembali kepada pemiliknya. Dompet yang sudah sekali mengirim di dalam jendela yang sama punya lebih sedikit daripada yang disiratkan angka utama delegasinya, dan yang berhenti adalah transfer yang belakangan — yang dari luar terbaca seperti transfer yang sama gagal secara acak.
Batasnya nol. Nol adalah nilai yang benar ketika energinya pasti, dan di mode B, tempat kami sendiri yang mengantar energinya dan menyiarkan transaksinya, fee_limit justru yang kami minta Anda biarkan kosong: sebuah batas di situ tidak lain adalah izin permanen untuk membakar TRX pengirim kalau ada yang meleset. Ia juga penghenti mutlak. Izin nol berarti panggilan yang kurang satu unit saja akan berhenti alih-alih membayarnya, jadi batas yang dibiarkan nol adalah keputusan yang hanya berlaku selama energinya berlaku.
Melihatnya sebelum transaksinya ditandatangani
Pertanyaan di balik pemicu yang pertama — berapa energi yang dimakan penerima ini — bisa dijawab sebelum apa pun ditandatangani, oleh dua panggilan yang tidak mencadangkan apa pun dan tidak menagih apa pun.
GET /v1/address-check menjawab untuk satu alamat: activated, holds_usdt, blacklisted, is_contract, dan expected_kind yang mengikuti dari semuanya. holds_usdt adalah yang menentukan besar panggilannya.
curl -s -H "Authorization: Bearer $KEY" \ "https://api.nrg.market/v1/address-check?address=TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9" # expected_kind bernilai "single", "double" atau "custom"
POST /v1/estimate menjawab untuk satu pesanan massal — sampai 500 penerima dalam satu panggilan, masing-masing dengan sebuah kind, energy_units di baliknya dan warnings yang ada. single adalah transfer biasa dan double yang membuka akun token. custom adalah posisi yang tidak tercakup patokan mana pun: penerimanya ternyata sebuah kontrak dengan logika transfer-nya sendiri, jadi tidak satu pun angka baku berlaku dan energy_units-nya datang dari dry-run panggilan yang sesungguhnya. Posisi seperti itulah yang batasnya perlu diukur satu per satu, dan peringatan contract_recipient di sebelahnya sering menjadi tanda pertama bahwa sebuah alamat pembayaran sama sekali bukan dompet.
Perbaikannya, dari yang paling mudah
Naikkan batasnya. Satu field, tanpa infrastruktur, dan penghentiannya lenyap: panggilannya selesai dan jaringan mengambil apa yang dibutuhkannya. Biayanya tidak ikut lenyap. Sebuah batas adalah izin untuk membakar, jadi batas yang longgar adalah pembakaran yang longgar — transfer yang tadinya berhenti kini selesai dengan 13.1 TRX. Benar sebagai lantai di bawah satu putaran pembayaran, salah sebagai rencana.
Taruh energi pada pengirimnya. Dengan begitu tidak ada lagi yang perlu diizinkan oleh batas itu. Energi datang dari staking TRX, yang berarti mengunci saldo kerja dan mengawasi anggaran sumber daya, atau dari menyewa sebuah delegasi selama beberapa menit yang dibutuhkan sebuah transfer (berapa biayanya saat ini). Dengan cara mana pun panggilannya dibayar dalam energi dan tidak ada pembakaran sama sekali.
Kirimlah di dalam jendelanya. Energi sewaan ada di dompet selama satu jangka, dan respons sebuah pesanan membawa send_before — saat jendela pengirimannya tutup, tiga detik sebelum jangka yang Anda beli habis. Pantau munculnya field itu alih-alih kata ready: pesanannya dipenuhi oleh pengiriman energi, jadi completed menyusul seketika sesudahnya. Mengirim setelah send_before berarti melemparkan transfer ke jaringan ketika energinya mungkin sudah pulang, dan itu persis kekurangan yang dibicarakan tulisan ini.
Serahkan transaksi yang sudah ditandatangani. Mode B mengangkat urusan jendela dari sisi Anda sepenuhnya: Anda mengirimkan transfer yang sudah ditandatangani, kami menahannya, dan kami menyiarkannya begitu energinya terkonfirmasi on-chain. Kalau transaksi yang kami siarkan tetap sampai ke sebuah blok tanpa tereksekusi, posisinya ditutup failed dengan transaction_reverted dan seluruh cadangannya dilepas — sebab itu, seperti tiap sebab lain dalam daftar ini, tidak pernah ditagihkan. Bacalah namanya apa adanya: transaction_reverted adalah kata kami untuk “ia sampai ke sebuah blok dan tidak tereksekusi”, apa pun kata jaringan sendiri untuk penolakan itu, jadi sebuah OUT_OF_ENERGY dan REVERT milik sebuah kontrak datang di bawah status yang sama. TRX yang dibakar transaksi semacam itu dalam perjalanannya menuju vonis tersebut adalah milik pengirim dan bukan milik kami, dan itulah alasan untuk estimasi di awal bagian ini alih-alih loop percobaan ulang di ujungnya.