Solidity v0.8.0 İşleyişi Bozan Değişiklikler
Bu bölüm, Solidity 0.8.0 sürümünde sunulan ana işleyişi bozan değişiklikleri vurgular. Tam liste için sürüm değişiklik günlüğü adresini kontrol edin.
Semantikte Sessiz Değişiklikler
Bu bölüm, derleyici size bildirmeden mevcut kodun davranışını değiştirdiği değişiklikleri listeler.
Aritmetik işlemler alttan taşma ve üstten taşma durumunda geri döner. Önceki paketleme davranışını kullanmak için
unchecked { ... }
öğesini kullanabilirsiniz.Üstten taşma kontrolleri çok yaygındır, bu nedenle gaz maliyetlerinde hafif bir artışa neden olsa bile kodun okunabilirliğini artırmak için bunları varsayılan hale getirdik.
ABI coder v2 varsayılan olarak etkinleştirilmiştir.
Eski davranışı kullanmayı
pragma abicoder v1;
kullanarak seçebilirsiniz. Pragmapragma experimental ABIEncoderV2;
hala geçerlidir, ancak kullanımdan kaldırılmıştır ve hiçbir etkisi yoktur. Eğer doğrudan belirtmek istiyorsanız, lütfen bunun yerinepragma abicoder v2;
kullanın.ABI coder v2’nin v1’den daha fazla türü desteklediğini ve girdiler üzerinde daha fazla sanity kontrolü gerçekleştirdiğini unutmayın. ABI coder v2 bazı fonksiyon çağrılarını daha pahalı hale getirir ve ayrıca parametre tiplerine uymayan veriler içerdiklerinde ABI coder v1 ile geri dönmeyen sözleşme çağrılarının geri dönmesine neden olabilir.
Üs alma sağdan ilişkilidir, yani
a**b**c
ifadesia**(b**c)
olarak ayrıştırılır. 0.8.0’dan önce(a**b)**c
olarak ayrıştırılıyordu.Bu, üs alma operatörünü ayrıştırmanın yaygın yoludur.
Başarısız iddialar ve sıfıra bölme veya aritmetik üstten taşma gibi diğer dahili kontroller geçersiz işlem kodunu değil, bunun yerine geri döndürme işlem kodunu kullanır. Daha spesifik olarak,
Panic(uint256)
fonksiyon çağrısına eşit hata verilerini, koşullara özgü bir hata koduyla kullanacaklardır.Bu, hatalarda gaz tasarrufu sağlarken, statik analiz araçlarının bu durumları, başarısız bir
require
gibi geçersiz bir girdi üzerindeki bir geri dönüşten ayırt etmesine izin verir.Depolama alanında uzunluğu yanlış kodlanmış bir bayt dizisine erişilmesi paniğe neden olunur. Depolama bayt dizilerinin ham gösterimini değiştirmek için inline assembly kullanılmadığı sürece bir sözleşme bu duruma giremez.
Dizi uzunluğu ifadelerinde sabitler kullanılması halinde Solidity’nin önceki sürümleri, değerlendirme ağacının (evaluation tree) tüm dallarında (branch) rastgele (arbitrary) kesinlik kullanırdı. Artık, sabit değişkenler ara ifadeler olarak kullanıldığında, değerleri, çalışma zamanı ifadelerinde kullanıldıklarında olduğu gibi uygun şekilde yuvarlanacaktır.
byte
türü kaldırıldı. Bubytes1
türünün bir takma adıydı.
Yeni Kısıtlamalar
Bu bölümde, mevcut sözleşmelerin artık derlenmemesine neden olabilecek değişiklikler listelenmektedir.
Literallerin açık dönüşümleri ile ilgili yeni kısıtlamalar vardır. Aşağıdaki durumlarda önceki davranış muhtemelen belirsizdi:
Negatif literallerden ve
type(uint160).max
değerinden büyük literallerdenaddress
değerine açık dönüşümlere izin verilmez.Literaller ve
T
tamsayı tipi arasındaki açık dönüşümlere yalnızca literaltype(T).min
vetype(T).max
arasında yer alıyorsa izin verilir. Özellikle,uint(-1)
kullanımlarınıtype(uint).max
ile değiştirin.Literaller ve enumlar arasındaki açık dönüşümlere yalnızca literal enumdaki bir değeri temsil edebiliyorsa izin verilir.
Literaller ve
address
türü arasındaki açık dönüşümler (örneğinaddress(literal)
)address payable
yerineaddress
türüne sahiptir. Açık bir dönüşüm, yanipayable(literal)
kullanılarak payable(ödenebilir) bir adres türü elde edilebilir.
Address literals,
address payable
yerineaddress
türüne sahiptir. Açık bir dönüşüm kullanılarakaddress payable
türüne dönüştürülebilirler, örneğinpayable(0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF)
.Açık tip dönüşümlerinde yeni kısıtlamalar vardır. Dönüşüme yalnızca işaret, genişlik veya tür kategorisinde en fazla bir değişiklik olduğunda izin verilir (
int
,adres
,bytesNN
, vb.). Birden fazla değişiklik yapmak için birden fazla dönüşüm kullanın.Burada,
T
veS
tipleri vex
deS
tipindeki herhangi bir rastgele(arbitrary) değişken olmak üzere,T(x)
açık dönüşümünü belirtmek içinT(S)
notasyonunu kullanalım. Hem genişliği (8 bitten 16 bite) hem de işareti (işaretli tamsayıdan işaretsiz tamsayıya) değiştirdiği için bu tür bir izin verilmeyen dönüştürmeye örnek olarakuint16(int8)
verilebilir. Dönüştürmeyi yapmak için bir ara türden geçmek gerekir. Önceki örnekte, buuint16(uint8(int8))
veyauint16(int16(int8))
olacaktır. Dönüştürmenin iki yolunun farklı sonuçlar üreteceğini unutmayın, örneğin-1
için. Aşağıda, bu kural tarafından izin verilmeyen bazı dönüşüm örnekleri verilmiştir.
address(uint)
veuint(address)
: hem tür kategorisini hem de genişliği dönüştürüyor. Bunu sırasıylaaddress(uint160(uint))
veuint(uint160(address))
ile değiştirin. -payable(uint160)
,payable(bytes20)
vepayable(integer-literal)
: hem tür kategorisini hem de durum değiştirilebilirliğini dönüştürüyor. Bunu sırasıylapayable(address(uint160))
,payable(address(bytes20))
vepayable(address(integer-literal))
ile değiştirin.payable(0)``ın geçerli olduğunu ve kuralın bir istisnası olduğunu unutmayın. - ``int80(bytes10)
vebytes10(int80)
: hem tür kategorisini hem de işareti dönüştürüyor. Bunu sırasıylaint80(uint80(bytes10))
vebytes10(uint80(int80)
ile değiştirin. -Contract(uint)
: hem tür kategorisini hem de genişliği dönüştürüyor. BunuContract(address(uint160(uint)))
ile değiştirin.Belirsizliği önlemek için bu dönüşümlere izin verilmemiştir. Örneğin,
uint16 x = uint16(int8(-1))
ifadesinde,x
değeri, işaret ve genişlik dönüşümünden hangisinin önce uygulandığına bağlı olacaktır.
Fonksiyon çağrı seçenekleri sadece bir kez verilebilir, yani
c.f{gas: 10000}{value: 1}()
geçersizdir vec.f{gas: 10000, value: 1}()
olarak değiştirilmelidir.Global fonksiyonlar
log0
,log1
,log2
,log3
velog4
kaldırılmıştır.Bunlar büyük ölçüde kullanılmayan düşük seviyeli fonksiyonlardır. Davranışlarına inline assembly’den erişilebilir.
enum
tanımları 256`dan fazla üye içeremez.Bu, ABI’deki temel türün her zaman
uint8
olduğunu varsaymayı güvenli hale getirecektir.Public fonksiyonlar ve event`ler haricinde
this
,super
ve_
isimli açıklamalara izin verilmez. İstisna, bu tür fonksiyon isimlerine izin veren Solidity dışındaki dillerde uygulanan sözleşmelerin arayüzlerini açıklamayı mümkün kılmaktır.Koddaki
\b
,\f
ve\v
kaçış dizileri için destek kaldırılmıştır. Bunlar, onaltılık kaçış dizileri aracılığıyla eklenmeye devam edebilir; örneğin, sırasıyla\x08
,\x0c
ve\x0b
.Global değişkenler
tx.origin
vemsg.sender
,address payable
yerineaddress
tipine sahiptir. Bunlar, açık bir dönüşüm kullanılarakaddress payable
türüne, yanipayable(tx.origin)
veyapayable(msg.sender)
a dönüştürülebilir.Bu değişiklik, derleyicinin bu adreslerin ödenebilir olup olmadığını belirleyememesi nedeniyle yapılmıştır, bu nedenle artık bu gereksinimi görünür kılmak için açık bir dönüşüm gerektirmektedir.
address
türüne açık dönüşüm, her zaman, ödenebilir olmayan biraddress
türü döndürür. Özellikle, aşağıdaki açık dönüşümleraddress payable
yerineaddress
türüne sahiptir:u``nun ``uint160
türü bir değişken olduğuaddress(u)
.u
, iki açık dönüşüm kullanılarakpayable(address(u))
şeklindeaddress payable
türüne dönüştürebilir.b``nin ``bytes20
türü bir değişken olduğuaddress(b)
.b
, iki açık dönüşüm kullanılarakpayable(address(b))
şeklinde `` address payable`` türüne dönüştürebilir.c``nin bir sözleşme olduğu ``address(c)
. Önceden, bu dönüşümün dönüş türü, sözleşmenin Ether alıp alamayacağına (bir receive fonksiyonuna veya bir payable fallback fonksiyonuna sahip olarak) bağlıydı.payable(c)
dönüşümüaddress payable
türüne sahiptir ve yalnızcac
sözleşmesi Ether alabildiğinde bu dönüşüme izin verilir. Genel olarakc
, şu açık dönüşüm kullanılarak her zamanaddress payable
türüne dönüştürülebilir:payable(address(c))
.address(this)
türününaddress(c)
ile aynı kategoriye girdiğini ve aynı kuralların onun için de geçerli olduğunu unutmayın.
Inline assembly`de yerleşik
chainid
artıkpure
yerineview
olarak kabul edilmektedir.Tekli negasyon artık işaretsiz tamsayılar üzerinde kullanılamaz, sadece işaretli tamsayılar üzerinde kullanılabilir.
Arayüz Değişiklikleri
--combined-json
çıktısı değişti: JSON alanlarıabi
,devdoc
,userdoc
vestorage-layout
artık alt nesnelerdir. 0.8.0’dan önce string olarak serileştiriliyorlardı.“Eski AST” kaldırıldı (komut satırı arayüzünde
--ast-json
ve standart JSON içinlegacyAST
). Yerine “kompakt AST” (--ast-compact--json
sırasıylaAST
) kullanın.Eski hata raporlayıcı (
--old-reporter
) kaldırıldı.
Kodunuzu nasıl güncelleyebilirsiniz?
Aritmetik paketlemeye güveniyorsanız, her işlemi
unchecked { ... }
.İsteğe bağlı: SafeMath veya benzer bir kütüphane kullanıyorsanız,
x.add(y)
ifadesinix + y
,x.mul(y)
ifadesinix * y
vb. olarak değiştirin.Eski ABI kodlayıcı ile devam etmek istiyorsanız
pragma abicoder v1;
ekleyin.İsteğe bağlı olarak
pragma experimental ABIEncoderV2
veyapragma abicoder v2
gereksiz olduğu için kaldırın.byte
ifadesinibytes1
olarak değiştirin.Gerekirse ara açık tip dönüşümler ekleyin.
c.f{gas: 10000}{value: 1}()
ifadesinic.f{gas: 10000, value: 1}()
olarak birleştirin.msg.sender.transfer(x)
öğesinipayable(msg.sender).transfer(x)
olarak değiştirin veyaaddress payable
türü saklanmış bir değişken kullanın.x**y**z
ifadesini(x**y)**z
olarak değiştirin.log0
, …,log4
yerine inline assembly kullanın.İşaretsiz tamsayıları, türün maksimum değerinden çıkarıp 1 ekleyerek negatifleştirin (örneğin
type(uint256).max - x + 1
,x
in sıfır olmadığından emin olarak)