Paylaşımlı Ödeme

Spread the love

Blokzincir yapılarının bize sağladığı avatanjlardan biri de bir ödemeyi gerekirse 1000 adrese bölerek gönderebilme özelliği. Diyelim ki bir afet durumunda afet durumundaki depremzedelere 10.000 TL bağış yapacaksınız fakat bunun 1000 farklı kişiye 10 TL olarak gittiğini garanti etmek istiyorsunuz. Geleneksel finans sisteminde bu bir hayli zahmetli bir iş olabilir. Fakat akıllı kontratlar ile bunu rahatlıkla yapabiliriz.

Benzer bir sistem şans oyunu tarzı sistemlerde de kullanılmaktadır. Yine içeriği görülebilen bir akıllı kontrat üzerinden yapılacak çekilişte toplam biriken tutar örneğin katılımcıların %90’ına bölünerek dağıtılabilir. Fakat şans oyunu tarzı uygulamalar yasal olarak farklı bir statüde ele alındığı için hukuksal boyutuna hakim olmadan böyle bir Dapps yani, dağıtık uygulama geliştirmeniz cezai süreçlere yol açabilmektedir.

Biz örneğimizde hesap sahibinin ödemesini önceden belirlediğimiz 2 adrese belirlediğimiz oranda bölerek göndereceğiz. Eğitim amaçlı 2 adres kullanıldı. 2 değil 20 de 200 de olabilir.

Öncelikle kodumuzun tamamını paylaşalım. Ardından bölüm bölüm yorumlayalım.

from pyteal import *

#Split Payment, tmpl_own tarafından tmpl_rcv1 ve tmpl_rcv2 arasındaki ödemeyi tmpl_ratn / tmpl_ratd oranında

# bölerek gönderim yapar.

“””Split Payment”””

tmpl_fee = Int(1000)

tmpl_rcv1 = Addr(“6ZHGHH5Z5CTPCF5WCESXMGRSVK7QJETR63M3NY5FJCUYDHO57VTCMJOBGY”)

tmpl_rcv2 = Addr(“7Z5PWO2C6LFNQFGHWKSK5H47IQP5OJW2M3HA2QPXTY3WTNP5NU2MHBW27M”)

tmpl_own = Addr(“5MK5NGBRT5RL6IGUSYDIX5P7TNNZKRVXKT6FGVI6UVK6IZAWTYQGE4RZIQ”)

tmpl_ratn  = Int(1)

tmpl_ratd = Int(3)

tmpl_min_pay = Int(1000)

tmpl_timeout = Int(3000)

def split(tmpl_fee=tmpl_fee,

             tmpl_rcv1=tmpl_rcv1,

             tmpl_rcv2=tmpl_rcv2,

             tmpl_own=tmpl_own,

             tmpl_ratn=tmpl_ratn,

             tmpl_ratd=tmpl_ratd,

             tmpl_min_pay=tmpl_min_pay,

             tmpl_timeout=tmpl_timeout):

    split_core = And(

        Txn.type_enum() == TxnType.Payment,

        Txn.fee() < tmpl_fee,

        Txn.rekey_to() == Global.zero_address()

    )

    split_transfer = And(

        Gtxn[0].sender() == Gtxn[1].sender(),

        Txn.close_remainder_to() == Global.zero_address(),

        Gtxn[0].receiver() == tmpl_rcv1,

        Gtxn[1].receiver() == tmpl_rcv2,

        Gtxn[0].amount() == ((Gtxn[0].amount() + Gtxn[1].amount()) * tmpl_ratn) / tmpl_ratd,

        Gtxn[0].amount() == tmpl_min_pay

    )

    split_close = And(

        Txn.close_remainder_to() == tmpl_own,

        Txn.receiver() == Global.zero_address(),

        Txn.amount() == Int(0),

        Txn.first_valid() > tmpl_timeout

    )

    split_program = And(

        split_core,

        If(Global.group_size() == Int(2),

            split_transfer,

            split_close

        )

    )

    return split_program

if __name__ == “__main__”:     print(compileTeal(split(), Mode.Signature))

Yine ilk satırda pyteal kütüphanemizi içe aktararak başlıyor ve ardından da değişkenlerimizi tanımlıyoruz.

Değişkenleri inceleyerek başlayalım.


Değişkenlerimizi tanımladıktan sonra split isimli metodumuzu oluşturacağız. En sonda da ana metoddan split metodunu çağıracağız.

Metodumuzu oluştururken yukarıda kullandığımız her değişkeni bir parametre olarak belirliyoruz.

Ardından da metodumuzun içine koşulları girmeye başlıyoruz. İlk koşulumuz split_core isminde.

    split_core = And(

        Txn.type_enum() == TxnType.Payment,

        Txn.fee() < tmpl_fee,

        Txn.rekey_to() == Global.zero_address()     )

Burada bir AND kapısı kullanarak; işlemin bir ödeme olduğunu TxnType.Payment ile, ödemenin maksimum ödeme tutarını aşmayacağını tmpl_fee ile ve Txn.rekey_to adresinin boş bir değer olduğunu Global.zero_address() ile belirliyoruz.

İkinci koşulumuza geçelim. Bu koşulumuzun ismi de split_transfer.

Burada kod biraz karışık gelebilir önce kısmı paylaşıp ardından dikkatlice inceleyelim.

    split_transfer = And(

        Gtxn[0].sender() == Gtxn[1].sender(),

        Txn.close_remainder_to() == Global.zero_address(),

        Gtxn[0].receiver() == tmpl_rcv1,

        Gtxn[1].receiver() == tmpl_rcv2,

        Gtxn[0].amount() == ((Gtxn[0].amount() + Gtxn[1].amount()) * tmpl_ratn) / tmpl_ratd,

        Gtxn[0].amount() == tmpl_min_pay     )

Gtxn[0].sender() == Gtxn[1].sender(), yani [0] numaralı hesabın göndericisiyle [1] numaralı hesabın göndericisi aynı kişi. Bu da bizim ilk başta tmpl_own değişkeniyle tanımladığımız hesap olacak.

Txn.close_remainder_to() == Global.zero_address(),işlem gerçekleştikten sonra adresi zero adrese eşitle. Bu işlem sonrası zero adrese eşitleme artık bir varsayılan gibi akıllı kontratlarda.

Gtxn[0].receiver() == tmpl_rcv1,

Gtxn[1].receiver() == tmpl_rcv2, satırlarıyla birinci ve ikinci alıcının kim olduğunu belirtiyoruz.

Gtxn[0].amount() == ((Gtxn[0].amount() + Gtxn[1].amount()) * tmpl_ratn) / tmpl_ratd, bu kısım tamamen matematik. [0] numaralı alıcıya gidecek para [0] ve [1] in toplamının tmpl_ratn ile çarpımı ve bu sonucun da tmpl_ratd e bölümü. Burada bir oran orantı işlemi yapıyoruz. Siz kendi kontratınızda bu değerler ile oynayabilirsiniz.

Gtxn[0].amount() == tmpl_min_pay, kısmında ise [0] numaralı yani daha az para alacak hesabın ücreti minumum ödeme tutarına eşit olsun diyoruz.

Split_Transfer koşulu içinde yer alan bu durumların tamamını AND kapısından geçirerek her birinin doğrulanması gerektiğini belirtiyoruz.

Sonraki koşulumuzun ismi split_close.  Kodumuz şu şekilde.

    split_close = And(

        Txn.close_remainder_to() == tmpl_own,

        Txn.receiver() == Global.zero_address(),

        Txn.amount() == Int(0),

        Txn.first_valid() < tmpl_timeout     )

Txn.close_remainder_to() == tmpl_own, kalan para hesabın sahibinde kalsın. Alıcının adresi Txn.receiver() == Global.zero_address(), ile sıfırlansın. Tutar Txn.amount() == Int(0), ile sıfırlansın. Txn.first_valid() > tmpl_timeout kısmıyla zaman aşımının altında bir sürede işlemin gerçekleştiğini belirtiyoruz. Yine bu koşulların hepsini AND kapısından geçirerek koşulumuzu oluşturuyoruz.

Ardından split_program ile ana koşulumuzu oluşturup önceki koşulları topluca ele alıyoruz.

    split_program = And(

        split_core,

        If(Global.group_size() == Int(2),

            split_transfer,

            split_close

        )     )

Bu ana kapıda split_core u direk alıyor. Sonrasında grup boyutu 2 ise, yani iki kişi ödeme alıyorsa,  split_transfer ve split_close u da sağlasın diyoruz.

Son olarak; return split_program metodumuzun split_program koşuluna dönmesini istiyoruz.

Metodumuz tamamen hazır. Sadece ana metoddan çağırarak derleme işlemini yapmamız gerekiyor. Bunun için de aşağıdaki kodu kullanıyoruz. Pyteal kütüphanesi içindeki compileTeal hazır fonksiyonuyla Python kodumuzu TEAL dilinde bir akıllı kontrata çeviriyoruz.

if __name__ == “__main__”:     print(compileTeal(split(), Mode.Signature))

Çıktıya bakalım.

#pragma version 2

txn TypeEnum

int pay

==

txn Fee

int 1000

&&

txn RekeyTo

global ZeroAddress

==

&&

global GroupSize

int 2

==

bnz l0

txn CloseRemainderTo

addr 5MK5NGBRT5RL6IGUSYDIX5P7TNNZKRVXKT6FGVI6UVK6IZAWTYQGE4RZIQ

==

txn Receiver

global ZeroAddress

==

&&

txn Amount

int 0

==

&&

txn FirstValid

int 3000

&&

b l1

l0:

gtxn 0 Sender

gtxn 1 Sender

==

txn CloseRemainderTo

global ZeroAddress

==

&&

gtxn 0 Receiver

addr 6ZHGHH5Z5CTPCF5WCESXMGRSVK7QJETR63M3NY5FJCUYDHO57VTCMJOBGY

==

&&

gtxn 1 Receiver

addr 7Z5PWO2C6LFNQFGHWKSK5H47IQP5OJW2M3HA2QPXTY3WTNP5NU2MHBW27M

==

&&

gtxn 0 Amount

gtxn 0 Amount

gtxn 1 Amount

+

int 1

*

int 3

/

==

&&

gtxn 0 Amount

int 1000

==

&&

l1: &&

Yukarıdaki şekilde kontratımız sorunsuz bir şekilde oluştu.

You may also like...