click here if you want to see your banner on this site

Author Topic: Overdraft smart contract gamit ang pyteal  (Read 685 times)

Scofield

  • Novice
  • *
  • Posts: 11
  • Karma: +0/-0
    • View Profile
Overdraft smart contract gamit ang pyteal
« on: September 24, 2020, 06:54:14 AM »


Ang mga hosting Smart Contract ay isa sa mga mahusay na tampok ng mga potensyal na teknolohiya ng Algorand na kung saan maraming mga developer ay hindi pa natutuklasan. Kung mayroon ka na nakasulat na code at naka-deploy sa Ethereum network gamit ang solidity, mabubunyag mo ang mga kaguluhan na kasangkot upang maitama ang mga bagay. Sa artikulong ito, ipapakita ko sa iyo kung paano ka maaaring sumulat ng mga tagubilin upang mabantayan ang isang transaksyon gamit ang teal. Ito ay isang intermediate hanggang sa advanced na antas ng disenyo ng kontrata, samakatuwid dapat kang magkaroon ng mahusay na kaalaman sa wika ng phyton, at/o statically typed na mga wika ng programming ay magiging isang karagdagang kalamangan.

Ano ang matututunan mo
  • Paano magsulat at mag-deploy ng mga smart contract sa Algorand blockchain.
  • Pag-unawa sa Pyteal/Teal na wika
  • Nesting sa Pyteal


Mga tool/Kinakailangan
  • Patakbuhin ang isang node o gumamit ng Docker sandbox o isang endpoint/serbisyong API kung hindi mo maaaring mapatakbo ng isang node sa iyong machine. Maipapayo na magpatakbo ka ng isang goal-CLI na kasama ng pagpapatakbo ng isang node. Sundin ang node installation guide.
  • Isang editor. Kung nais mong magmungkahi ako ng isa, inirerekumenda ko ang Pycharm.
  • Python Application
  • Algorand python SDK
  • Algodesk
Sumali sa developer forum upang matuto nang higit pa.

 
Overdraft/Linya Ng Kredito
Isaalang-alang ang isang senaryo, kung saan nagpunta si Alice sa tindahan (kung saan ang ating asset ay tinanggap bilang isang paraan ng pagbabayad) para sa mga pinamili na nagkakahalaga ng halagang $2,500. Gumamit si Alice ng isang kard na inisyu natin para sa pagbili. Sa puntong ito, ang transaksyon ay hindi makukumpleto dahil ang natira ay $1,500 sa kanyang wallet. Nais niyang magkaroon ng isang serbisyo na maaaring makasasalba sa kanya sa gulo na ito. Iminungkahi ito sa amin ni Alice. Ang ating koponan ay itinuturing na akma upang isama ang naturang serbisyo na nagpapahintulot kay Alice na labis na ma-overdraw ang kanyang account na ibinigay sa aming back-end na maaaring maalala na nakita si Alice sa paligid at kung ang ilang mga kundisyon ang natutugunan.

Ang kailangan lang natin ay ang paglalagay ng smart contract upang mahawakan natin ito. Ang Teal, isang akronim para sa Transaction Execution Approval Language ay napakalakas para sa hangarin tulad ng ipinahihiwatig ng pangalan.  Ang Teal bilang isang assembly language na katumbas ng alinman sa oo o hindi na ifi-feed sa mga opcode. Ang Pyteal ay binuo upang maalis ang mga complexity ng pagtatrabaho gamit ang mga binary dahil ang Teal ay higit pa sa pagbabasa ng mga naka-assemble na 1 at 0. Ito ay isang wika na nagbubuklod para sa Teal. Nang walang karagdagang ado, gawin natin ang napag-kasunduan.

 
Mga bagay na dapat tandaan

Nag-import ako ng ilang mga module mula sa nakaraan kong tutoryal na magagamit sa github. Upang mapanatili itong maiikli at simple, mas tumututuon ako sa mga pyteal code.

Ang source code ay nilalaman sa overdraft.py file. Lumikha ng isa sa iyong editor. Kopyahin at i-paste ang code sa ibaba.

Code: [Select]
from pyteal import *
from algosdk.future import transaction
from connection import algo_client, params
from assetInfo import transferasset, asset_manage_authorized, assetinformation, jointAuthorization, accounts_sk
from algosdk.transaction import AssetTransferTxn, encoding
from printAssetHolding import print_asset_holding
from waitForConfirmation import wait_for_confirmation
from algosdk.future.transaction import AssetTransferTxn, transaction
import base64

# Set the global variables
tmpl_fee = Int(1000)
tmpl_timeout = Int(6)
tmpl_period = Int(5)
min_algo_bal = Int(1000)
min_Freth_bal = Int(5000)
int_rate = Div(Int(8), Int(100))  # Interest on OD
flat_charge = Int(100)  # Flat charges for overdrawing in custom asset
max_gold_client = Int(300000)
max_ruby_client = Int(70000)
stake = False
assetId = 9604118
noReEntrancy = Bytes("base64", "19faf42c")
tmpl_OD = Sha256
sender = 'N6SJLDQXCXZ7IJMLM5VVEAWJ36JUJSDQVNQFA2I3BKFOWE3QLKKJGATPJ4'

userDict = {
    "user100": "...",
    "user101": "G26HOW2LWOV2PRE3WN7S7JDOWE32GR4SRZ34MLANCJPKVLIX4YNBNBT2XA",
    "user102": "..."
}


# Check if user can enjoy this service i.e is a potential client list and has required amount of asset staked.
def isAClient(addr):
    global stake
    if addr in userDict:
        stake = True
        return int(1)
    else:
        stake = stake
        return int(0)


# Function requesting overdraft
def requestOdrft(addr, amt):

    bal_In_Algo = algo_client.account_info(addr)['amount-without-pending-rewards']  # To check if user is eligible, scrutinize their balance in
    bal_In_Freth = algo_client.account_info(addr)['assets'][0]['amount']  # Both in Freth and Algo so the transaction will not fail due to low balance.
    alc_bal_Freth = Int(bal_In_Freth) # Balance of Drawer in Freth
    alc_bal_ALGO = Int(bal_In_Algo) # Balance of Drawer in ALGO
    is_pot_client = isAClient(addr) # Is this user contained in the userList?
    isRubyUser = Le(Int(amt), max_ruby_client) # A Ruby user can obtain loan not greater than 70000 Freth
    isGoldUser = And(isRubyUser, Gt(Int(amt), max_ruby_client), Le(Int(amt), max_gold_client))  # A Gold user can overdraw up to 300,000 Freth. This is the maximum we can allow subscribers to overdraw.

    # Check that the account balance is less than requested amount
    # Drawer must be holding at least 20,000 worth of Freth at this time.
    # Balance in ALGO at this time must not go below 2000.
    # To enable for transaction fee and in this contract, balance is considered zero when
    # goes below 2000
    # compute total loan to disburse less interest and other charges if any
    net_loan = Minus(Int(amt), Add(Mul(int_rate, Int(amt)), flat_charge))

    # Check transaction fields are correct
    # Check the status of user's account.
    # User must be holding an amount of Freth as staking at this time.
    # Balance in ALGO at this time must not go below amount for transaction fee.
    # To enable for transaction fee and in this contract, balance is considered zero when
    # goes below 2000

    # Conditions for approving transaction
    ovdrft_trxn_cond = And(  # including
        And(  # including
            And(  # And inclusive of..
                Txn.type_enum() == Int(4),  # Transaction type is asset transfer
                Le(Txn.fee(), tmpl_fee),  # Transaction fee cannot exceed stipulated amount to guard against any attack intending to overstate transaction fee.
                Eq(Txn.amount(), net_loan),  # Amount requested as overdraft cannot exceed balance less interest plus other charges
                Eq(Txn.lease(), noReEntrancy),  # Guard for transaction parameters
                Eq(Txn.xfer_asset(), Int(assetId)), # Pointing to specific asset we have access to.
            ),
            Eq(Int(is_pot_client), Int(1)),  # This caller must be an already subscriber. ie A user in our list
            Le(alc_bal_ALGO, min_algo_bal),  # and balances of user in ALGO & Freth(custom asset) are within our requirements.
            Lt(alc_bal_Freth, min_Freth_bal)
        ),
        Or(
            Eq(isRubyUser, Int(1)),  # check that requested loan is within specified windows
            Eq(isGoldUser, Int(1))  # The caller should be either a Ruby user or a Gold user.
        ),
        And(
            Le(Txn.last_valid(), Int(6)),  # Transaction valid round should not exceed set time, else panic.
            Eq(Txn.asset_close_to(), Addr(asset_manage_authorized)),  # Asset balance is closed to a contract account so no ambiguous meaning to rechannelling an asset can pass.
            Eq(Txn.asset_receiver(), Addr(addr))  # Receiver cannot be any other than caller.
        )
    )
    opcodes = ovdrft_trxn_cond.teal() # To create teal
    return opcodes


Ang pag-convert ng mga pyteal code sa teal ay bumubuo ng mga sumusunod na opcode.
Code: [Select]
txn TypeEnum
int 4
==
txn Fee
int 1000
<=
&&
txn Amount
int 20000
int 8
int 100
/
int 20000
*
int 100
+
-
==
&&
txn Lease
byte base64 19faf42c
==
&&
txn XferAsset
int 10897078
==
&&
int 0
int 1
==
&&
int 99999000
int 1000
<=
&&
int 1000
int 5000
<
&&
int 20000
int 70000
<=
int 1
==
int 20000
int 70000
<=
int 20000
int 70000
>
&&
int 20000
int 300000
<=
&&
int 1
==
||
&&
txn LastValid
int 6
<=
txn AssetCloseTo
addr NFZ3L6E4MLIOQ5RWYYRJLHCELIA4Q2HA2U654DTKHMBCUQASCDVLLBEXAQ
==
&&
txn AssetReceiver
addr G26HOW2LWOV2PRE3WN7S7JDOWE32GR4SRZ34MLANCJPKVLIX4YNBNBT2XA
==
&&
&&

Kung pamilyar ka sa layunin, nagbigay ako ng isang sanggunian upang matulungan ka sa yugto ng compilation at kung paano manipulahin ang mga resulta upang lumikha ng isang logic signature. Maaari mong gamitin ang boilerplate na ito kung ma-aaccess mo ang goal-CLi o algodesk na nagbabalik ng base64 encoded program bytes at base32 SHA512_256 hash ng program bytes (Address style), eksakto kung ano ang kailangan natin.

Mula sa nabasa ang boilerplate:

Ngayon na ipinatupad ang pangunahing kontratang kailangan natin upang bumuo ng isang halimbawa ng instantiating ng kontrata. Gagawin natin ito sa pamamagitan ng paglikha ng isang python file na pinangalanang 'odrft_deploy.py'. Una nating itinakda ang mga variable ng template at pagkatapos ay pagtawag ng ovdrft function na nilikha natin sa mga nakaraang hakbang. Susunod, gagamit  tayo ng phyton upang matawag ang command line upang ma-compile ang TEAL program sa pamamagitan ng pag-save ng TEAL code sa isang file at paggamit ng execute function. Sa wakas ay nabasa natin ang file na naglalaman ng pinagsamang TEAL bytes pabalik sa isang lokal na variable.

Tandaan: Gumawa ako ng ilang pagbabago. Palitan ang htlc file sa ovdrft

Code: [Select]
#!/usr/bin/env python3

import uuid, base64
from algosdk import algod, transaction, account, mnemonic
from overdraft import requestOdrft  # A file where the opcode is contained.

#--------- compile & send transaction using Goal and Python SDK ----------
tmpl_hash_fn = Sha256
tmpl_hash_img = Bytes("base64", "QzYhq9JlYbn2QdOMrhyxVlNtNjeyvyJc/I8d8VAGfGc=")
teal_source = requestOdrft("G26HOW2LWOV2PRE3WN7S7JDOWE32GR4SRZ34MLANCJPKVLIX4YNBNBT2XA", 20000)
#print( teal_source )
# compile teal
teal_file = str(uuid.uuid4()) + ".teal"
with open(teal_file, "w+") as f:
    f.write(teal_source)
lsig_fname = str(uuid.uuid4()) + ".tealc"

stdout, stderr = execute(["goal", "clerk", "compile", "-o", lsig_fname,
                          teal_file])
if stderr != "":
    print(stderr)
    raise
elif len(stdout) < 59:
    print("error in compile teal")
    raise

with open(lsig_fname, "rb") as f:
    teal_bytes = f.read()

# ---------- Pagsamahin at magpadala ng transaksyon gamit ang Goal at Python SDK ----------

Karagdagang impormasyon:

1. I-import ang lahat ng mga utility mula sa pyteal module.
Code: [Select]
from python import *
2. Bawat expression ng pyteal ay dapat suriin sa isang binary (alinman sa isang TealType.bytes o TealType.uint64) expression.

3. Ang parehong mga kanan at kaliwa na operands ay dapat na magkatulad ng uri.
Code: [Select]
Int(2) == Int(4) # This is right:
Bytes(address) == Bytes(address) # This is right:
Int(2) == Bytes(address) # This is wrong ​

4. Ang paghahambing sa pagitan ng mga operand ay dapat magresulta sa alinman sa True o False na katumbas ng Int(1) o Int(0)

5. Sinusuportahan ng Pyteal ang overloading operator halimbawa:
  • Ang Le(Int(3), Int(2)) ay simpleng nagsasabi: suriin na ang 3 sa uri ng TealType.uint64 ay katumbas ng 2 ng parehong uri. Ang karagdagang impormasyon ay matatagpuan sa dokumentasyon ng Pyteal.

Gumawa ng Logic Signature At Mag-sign ng Isang Transaksyon Gamit Ito.
Code: [Select]
# Get the program and parameters and use them to create an lsig
# For the contract account to be used in a transaction
# In this example 'hype sense black soap loop lucky king number'
# hashed with sha256 will produce our a byte hash
# This creates a lock for the ovdrft contract
args = [
    "hype sense black soap loop lucky king number".encode()
]
# Add the program bytes and args to a LogicSig object
lsig = transaction.LogicSig(teal_bytes, args)
print( lsig.address() )

# Transfer asset
def transferAssets(rec, amount):
    params.fee = 1000
    params.flat_fee = True

    txn = AssetTransferTxn(
        sender=sender,
        sp=params,
        receiver=rec,
        amt=amount,
        index=assetId
    )

    lstx = transaction.LogicSigTransaction(txn, lgsig)
    txns = [lstx]
    transaction.write_to_file(txns, "ovrdrft.stxn", False)

    # Submit transaction to the network
    tx_id = algo_client.send_transaction(lstx, headers={'content-type': 'application/x-binary'})
    message = "Transaction was signed with: {}.".format(tx_id)
    wait = wait_for_confirmation(tx_id)
    isSuccessful = bool(wait is not None)
    print(isSuccessful)
    # Now check the asset holding for receiver.
    # This should now show a holding with the sent balance.
    assetHolding = print_asset_holding(rec, assetId)
    logging.info(
        "...##Asset Transfer... \nReceiving account: {}.\nMessage: {}\nOperation: {}\nHoldings: {}\n".format(
            rec,
            message,
            transferAssets.__name__,
            assetHolding
        ))



Konklusyon
Pinapagana ng Pyteal ang mga developer ng Algorand na ipahayag ang kanilang contract logic nang mas natural gamit ang python. Ang Pyteal code ay nai-convert sa teal opcodes gamit ang .teal() member function. Nagbibigay ito ng isang direkta at solong interpretasyon sa lohika ng programa sa gayon iniiwasan ang kalabuan. Samantala, ang mga developer ay mayroon ding sagutin ng pagsusulat nang mahusay, mabisa at ligtas na code. Makipag-ugnay sa mga mapagkukunan ng developer upang matuto nang higit pa tungkol sa Smart contract ng Algorand.

Code: [Select]
from pyteal import *
from algosdk.future import transaction
from connection import algo_client, params
from assetInfo import transferasset, asset_manage_authorized, assetinformation, jointAuthorization, accounts_sk
from algosdk.transaction import AssetTransferTxn, encoding
from printAssetHolding import print_asset_holding
from waitForConfirmation import wait_for_confirmation
from algosdk.future.transaction import AssetTransferTxn, transaction
import base64

# Set the global variables
tmpl_fee = Int(1000)
tmpl_timeout = Int(6)
tmpl_period = Int(5)
min_algo_bal = Int(1000)
min_Freth_bal = Int(5000)
int_rate = Div(Int(8), Int(100))  # Interest on OD
flat_charge = Int(100)  # Flat charges for overdrawing in custom asset
max_gold_client = Int(300000)
max_ruby_client = Int(70000)
stake = False
assetId = 9604118
noReEntrancy = Bytes("base64", "19faf42c")
tmpl_OD = Sha256
sender = 'N6SJLDQXCXZ7IJMLM5VVEAWJ36JUJSDQVNQFA2I3BKFOWE3QLKKJGATPJ4'

userDict = {
    "user100": "...",
    "user101": "G26HOW2LWOV2PRE3WN7S7JDOWE32GR4SRZ34MLANCJPKVLIX4YNBNBT2XA",
    "user102": "..."
}


# Check if user can enjoy this service i.e is a potential client list and has required amount of asset staked.
def isAClient(addr):
    global stake
    if addr in userDict:
        stake = True
        return int(1)
    else:
        stake = stake
        return int(0)


# Function requesting overdraft
def requestOdrft(addr, amt):

    bal_In_Algo = algo_client.account_info(addr)['amount-without-pending-rewards']  # To check if user is eligible, scrutinize their balance in
    bal_In_Freth = algo_client.account_info(addr)['assets'][0]['amount']  # Both in Freth and Algo so the transaction will not fail due to low balance.
    alc_bal_Freth = Int(bal_In_Freth) # Balance of Drawer in Freth
    alc_bal_ALGO = Int(bal_In_Algo) # Balance of Drawer in ALGO
    is_pot_client = isAClient(addr) # Is this user contained in the userList?
    isRubyUser = Le(Int(amt), max_ruby_client) # A Ruby user can obtain loan not greater than 70000 Freth
    isGoldUser = And(isRubyUser, Gt(Int(amt), max_ruby_client), Le(Int(amt), max_gold_client))  # A Gold user can overdraw up to 300,000 Freth. This is the maximum we can allow subscribers to overdraw.

    # Check that the account balance is less than requested amount
    # Drawer must be holding at least 20,000 worth of Freth at this time.
    # Balance in ALGO at this time must not go below 2000.
    # To enable for transaction fee and in this contract, balance is considered zero when
    # goes below 2000
    # compute total loan to disburse less interest and other charges if any
    net_loan = Minus(Int(amt), Add(Mul(int_rate, Int(amt)), flat_charge))

    # Check transaction fields are correct
    # Check the status of user's account.
    # User must be holding an amount of Freth as staking at this time.
    # Balance in ALGO at this time must not go below amount for transaction fee.
    # To enable for transaction fee and in this contract, balance is considered zero when
    # goes below 2000

    # Conditions for approving transaction
    ovdrft_trxn_cond = And(  # including
        And(  # including
            And(  # And inclusive of..
                Txn.type_enum() == Int(4),  # Transaction type is asset transfer
                Le(Txn.fee(), tmpl_fee),  # Transaction fee cannot exceed stipulated amount to guard against any attack intending to overstate transaction fee.
                Eq(Txn.amount(), net_loan),  # Amount requested as overdraft cannot exceed balance less interest plus other charges
                Eq(Txn.lease(), noReEntrancy),  # Guard for transaction parameters
                Eq(Txn.xfer_asset(), Int(assetId)), # Pointing to specific asset we have access to.
            ),
            Eq(Int(is_pot_client), Int(1)),  # This caller must be an already subscriber. ie A user in our list
            Le(alc_bal_ALGO, min_algo_bal),  # and balances of user in ALGO & Freth(custom asset) are within our requirements.
            Lt(alc_bal_Freth, min_Freth_bal)
        ),
        Or(
            Eq(isRubyUser, Int(1)),  # check that requested loan is within specified windows
            Eq(isGoldUser, Int(1))  # The caller should be either a Ruby user or a Gold user.
        ),
        And(
            Le(Txn.last_valid(), Int(6)),  # Transaction valid round should not exceed set time, else panic.
            Eq(Txn.asset_close_to(), Addr(asset_manage_authorized)),  # Asset balance is closed to a contract account so no ambiguous meaning to rechannelling an asset can pass.
            Eq(Txn.asset_receiver(), Addr(addr))  # Receiver cannot be any other than caller.
        )
    )
    opcodes = ovdrft_trxn_cond.teal() # To create teal
    return opcodes

« Last Edit: September 29, 2020, 01:31:16 AM by Scofield »

 

Bitcoin Garden 2013-2024, All rights reserved | Privacy Policy | DMCA | About Bitcoin Garden | Support & Services