OUT_OF_ENERGY: ücreti harcayıp hiçbir şey göndermeyen TRON hatası
Bir USDT transferi çıkar, cüzdan bir ücretin alındığını gösterir ve alıcının eline hiçbir şey geçmez. İşlem bir blokta durur — geri çevrilmemiştir, çöken bir düğüm de olmamıştır — ve tamamlanmış bir transferin SUCCESS yazdığı yerde bu işlemde OUT_OF_ENERGY yazar. TRON'da bu hata tam da söylediği şeydir: çağrının enerjisi yolun ortasında bitmiş ve çağrı durmuştur. İşte mekanizması, bir ödeme turunun ona üç ayrı yoldan nasıl girdiği ve çözümleri — en hızlısından, gerçekte en az tutana.
Sonuç aslında ne söylüyor
USDT göndermek bir akıllı sözleşmeye yapılan çağrıdır ve TRON'da sözleşme çalıştırmak sabit bir ücretle değil enerjiyle ölçülür (enerji nedir). Önce gönderenin kendi enerjisi harcanır. Bu enerji çağrıyı karşılamadığında ağ orada durmaz — geri kalanını, birim başına 100 sun olan protokol oranıyla gönderenin TRX'ini yakarak satın alır; ama yalnızca işlemin kendi fee_limit alanının izin verdiği kadar. O alan kimsenin tahsil ettiği bir ücret değildir. Bu tek çağrının, gönderenin TRX'inden ne kadarını yakmasına izin verildiğini gösteren bir tavandır.
Çağrı bitmeden tavana ulaşılırsa çalışma durur. O ana kadar yapılmış her durum değişikliği geri alınır, dolayısıyla hiçbir jeton yer değiştirmez; ağ da kararını, tamamlanmış bir çağrının SUCCESS taşıdığı yere yazar. O karar, bir blok gezgininin başarısız bir işlemin yanında gösterdiği sözcüktür ve bir düğümün contractRet olarak döndürdüğü alandır. İşlemin ağa ulaşmayan hiçbir yanı yoktur. Ağa ulaşmış ve parası bitene kadar yürütülmüştür.
TRX her iki durumda da harcanır
Geri alma transferi geri alır. Yakmayı geri almaz: tüketilen enerji, parası ödenmiş enerjidir. Gönderenin elinde, denemenin tavana giderken yaktığı kadar eksilmiş bir bakiye, yer değiştirmemiş jetonlar ve bir mutabakat betiğinin hiç duraksamadan ödeme diye kaydedeceği bir işlem özeti kalır.
Refleksle atılan yeniden denemeyi pahalı hamleye çeviren de budur. Aynı sınırla yapılan aynı transfer, aynı sonuç için aynı TRX'i harcar; başarısızlıklarını kendiliğinden yineleyen bir ödeme döngüsü de bunu, sonuç metnini bir insan okumadan önce birkaç kez yapabilir. Bir ödeme masasının karşılaştığı başarısızlıkların çoğu parayı sessizce götürür. Bu, parayı gürültüyle götürür ve yine de gözden kaçar, çünkü cüzdan bir ücret bildirir ve para hiçbir yerde yoktur.
Dün işleyen bir sınır neden işlemez olur
Alıcı değişti, sınır değişmedi. Bir ödeme turunun ilk karşılaştığı budur. Zaten USDT tutan bir adrese yapılan transfer yaklaşık 65,000 birim enerji ister; hiç USDT tutmamış bir adrese yapılan transferin ayrıca alıcının jeton hesabını da açması gerekir ve bu yaklaşık 131,000 birimdir — aynı miktarda para kımıldatmak için iki katı iştah. Birincisini yakmak protokol oranıyla 6.5 TRX, ikincisini yakmak 13.1 TRX tutar. Olağan duruma göre boyutlandırılmış bir tavan, yeni bir müşteriye ilk kez ödeme yapıldığında yarı yarıya yetersiz kalır ve toplu işte hiçbir şey farklı görünmez: bu, transferin değil alıcının bir özelliğidir.
Enerji vardı, artık yok. Bir devir, abonelik değil, bir süre için verilmiş bir miktardır. İlk transferin harcadığı, ikincisi için orada değildir; süre bitince de kalan sahibine geri döner. Aynı pencerede bir kez gönderim yapmış bir cüzdanda, devrin ilan edilen rakamının düşündürdüğünden azı vardır ve duran, sonraki transferdir — dışarıdan bakınca bu, aynı transferin rastgele başarısız olması gibi okunur.
Sınır sıfır. Enerji kesinse doğru değer sıfırdır; enerjiyi bizim teslim edip işlemin yayınını da bizim yaptığımız mode B'de fee_limit, boş bırakmanızı istediğimiz alandır: oradaki bir sınır, bir şeyler ters gittiğinde gönderenin TRX'ini yakmak için verilmiş kalıcı bir izinden başka bir şey olmazdı. Sıfır aynı zamanda sert bir duraktır. Sıfır izin, tek bir birim eksik kalan bir çağrının o birimi satın almak yerine durması demektir; dolayısıyla sıfırda bırakılmış bir sınır, yalnızca enerji durduğu sürece geçerli olan bir karardır.
İşlem imzalanmadan önce görmek
İlk tetikleyicinin arkasındaki soru — bu alıcı ne kadar enerjiye mal oluyor — hiçbir şey imzalanmadan önce, hiçbir şey ayırmayan ve hiçbir şey tahsil etmeyen iki çağrıyla yanıtlanabilir.
GET /v1/address-check tek bir adres için yanıt verir: activated, holds_usdt, blacklisted, is_contract ve bunlardan çıkan expected_kind. Çağrının boyutunu belirleyen alan holds_usdt'dir.
curl -s -H "Authorization: Bearer $KEY" \ "https://api.nrg.market/v1/address-check?address=TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9" # expected_kind "single", "double" ya da "custom" olur
POST /v1/estimate toplu iş için yanıt verir — tek çağrıda 500 alıcıya kadar, her biri bir kind, arkasındaki energy_units ve varsa warnings ile. single olağan transferdir, double ise jeton hesabı açandır. custom, hiçbir kaba kuralın kapsamadığı kalemdir: alıcının, kendi transfer mantığı olan bir sözleşme olduğu ortaya çıkar, dolayısıyla iki standart rakam da geçerli olmaz ve energy_units gerçek çağrının bir deneme çalıştırmasından gelir. Sınırı tek tek boyutlandırmanız gereken kalemler bunlardır; yanlarındaki contract_recipient uyarısı da bir ödeme adresinin aslında cüzdan olmadığının çoğu zaman ilk işaretidir.
Çözümler, en kolayı önce
Sınırı yükseltin. Tek bir alan, hiç altyapı yok ve durma ortadan kalkar: çağrı tamamlanır, ağ da ihtiyacı olanı alır. Maliyet onunla birlikte ortadan kalkmaz. Bir sınır yakma iznidir; dolayısıyla cömert bir sınır cömert bir yakmadır — eskiden duran transfer artık 13.1 TRX ile tamamlanır. Bir ödeme turunun altına serilen zemin olarak doğru, plan olarak yanlış.
Gönderene enerji koyun. O zaman sınırın izin vereceği bir şey kalmaz. Enerji ya TRX stake etmekten gelir — ki bu, çalışan bir bakiyeyi kilitlemek ve bir kaynak bütçesini kollamak demektir — ya da bir transferin ihtiyaç duyduğu birkaç dakika için bir devir kiralamaktan (bunun şu anda ne tuttuğu). Her iki durumda da çağrının bedeli enerjiyle ödenir ve hiç yakma olmaz.
Pencerenin içinde gönderin. Kiralanmış enerji cüzdanda bir süreliğine durur ve bir siparişin yanıtı send_before taşır — teslim penceresinin kapandığı an, satın aldığınız sürenin bitmesine üç saniye kala. ready sözcüğünü değil, o alanın görünmesini kollayın: sipariş enerjinin teslimiyle yerine getirilir, dolayısıyla completed onun hemen ardından gelir. send_before'dan sonra göndermek, transferi ağa enerjinin çoktan evine dönmüş olabileceği bir anda koyar; bu yazının konusu olan eksiklik de tam olarak budur.
İmzalanmış işlemi bize verin. Mode B pencereyi sizin tarafınızdan tamamen kaldırır: zaten imzalanmış bir transferi gönderirsiniz, biz tutarız ve enerji zincirde onaylandığında yayınlarız. Yayınladığımız bir işlem yine de çalışmadan bir bloka ulaşırsa pozisyon transaction_reverted ile failed olarak kapanır ve rezervin tamamı serbest bırakılır — bu neden de, listedeki her neden gibi, hiçbir zaman ücretlendirilmez. Adı neyse onu anlatır: transaction_reverted, ağın kendi ret sözcüğü ne olursa olsun, «bir bloka ulaştı ve çalışmadı» demenin bizim sözcüğümüzdür; dolayısıyla bir OUT_OF_ENERGY ile bir sözleşmenin kendi REVERT yanıtı aynı durumun altında gelir. Böyle bir işlemin o karara giderken yaktığı TRX bizim değil gönderenin TRX'idir; bu bölümün sonundaki yeniden deneme döngüsünün değil, başındaki tahminin gerekçesi de budur.