Mga aplikasyon ng Waves smart account: mula sa mga auction hanggang sa mga bonus program

Mga aplikasyon ng Waves smart account: mula sa mga auction hanggang sa mga bonus program

Ang Blockchain ay madalas na nauugnay lamang sa mga cryptocurrencies, ngunit ang mga lugar ng aplikasyon ng teknolohiya ng DLT ay mas malawak. Ang isa sa mga pinaka-promising na lugar para sa paggamit ng blockchain ay isang matalinong kontrata na awtomatikong isinasagawa at hindi nangangailangan ng tiwala sa pagitan ng mga partidong pumasok dito.

RIDE – isang wika para sa mga matalinong kontrata

Ang Waves ay bumuo ng isang espesyal na wika para sa mga matalinong kontrata - RIDE. Ang kumpletong dokumentasyon nito ay matatagpuan dito. At dito - artikulo sa paksang ito sa Habr.

Ang kontrata ng RIDE ay isang predicate at nagbabalik ng "true" o "false" bilang output. Alinsunod dito, ang transaksyon ay maaaring naitala sa blockchain o tinanggihan. Ganap na ginagarantiyahan ng matalinong kontrata ang katuparan ng mga tinukoy na kundisyon. Ang pagbuo ng mga transaksyon mula sa isang kontrata sa RIDE ay kasalukuyang hindi posible.

Sa ngayon, may dalawang uri ng Waves smart contract: mga smart account at smart asset. Ang isang matalinong account ay isang regular na account ng gumagamit, ngunit isang script ang nakatakda para dito na kumokontrol sa lahat ng mga transaksyon. Maaaring ganito ang hitsura ng isang script ng matalinong account, halimbawa:

match tx {
  case t: TransferTransaction | MassTransferTransaction => false
  case _ => true
}

Ang tx ay isang transaksyong pinoproseso na pinapayagan namin ang paggamit ng mekanismo ng pagtutugma ng pattern kung hindi ito isang transaksyon sa paglilipat. Ang pagtutugma ng pattern sa RIDE ay ginagamit upang suriin ang uri ng transaksyon. Maaaring iproseso ang lahat ng umiiral na account sa script ng smart account mga uri ng transaksyon.

Ang script ay maaari ding magdeklara ng mga variable, gumamit ng "if-then-else" na mga konstruksyon at iba pang mga pamamaraan para sa ganap na pagsuri ng mga kondisyon. Upang matiyak na ang mga kontrata ay may mapapatunayang pagkakumpleto at pagiging kumplikado (gastos) na madaling hulaan bago magsimula ang pagpapatupad ng kontrata, ang RIDE ay hindi naglalaman ng mga loop o jump statement.

Kasama sa iba pang mga tampok ng mga Waves account ang pagkakaroon ng isang "estado," iyon ay, ang estado ng account. Maaari kang magsulat ng walang katapusang bilang ng mga pares (key, value) sa estado ng account gamit ang mga transaksyon ng data (DataTransaction). Ang impormasyong ito ay maaaring maproseso sa pamamagitan ng REST API at direkta sa smart contract.

Ang bawat transaksyon ay maaaring maglaman ng hanay ng mga patunay, kung saan maaaring ilagay ang lagda ng kalahok, ID ng kinakailangang transaksyon, atbp.

Nagtatrabaho sa RIDE sa pamamagitan ng IDE ay nagbibigay-daan sa iyo upang makita ang pinagsama-samang view ng kontrata (kung ito ay pinagsama-sama), lumikha ng mga bagong account at magtakda ng mga script para dito, pati na rin magpadala ng mga transaksyon sa pamamagitan ng command line.

Para sa buong cycle, kabilang ang paggawa ng account, pag-install ng matalinong kontrata dito at pagpapadala ng mga transaksyon, maaari ka ring gumamit ng library para sa pakikipag-ugnayan sa REST API (halimbawa, C#, C, Java, JavaScript, Python, Rust, Elixir) . Upang magsimulang magtrabaho kasama ang IDE, i-click lamang ang BAGONG button.

Malawak ang mga posibilidad para sa paggamit ng mga matalinong kontrata: mula sa pagbabawal ng mga transaksyon hanggang sa ilang mga address (β€œblack list”) hanggang sa mga kumplikadong dApp.

Ngayon tingnan natin ang mga partikular na halimbawa ng paggamit ng mga matalinong kontrata sa negosyo: kapag nagsasagawa ng mga auction, insurance, at paggawa ng mga programa ng katapatan.

Mga Auction

Isa sa mga kundisyon para sa isang matagumpay na auction ay transparency: ang mga kalahok ay dapat magtiwala na imposibleng manipulahin ang mga bid. Ito ay makakamit salamat sa blockchain, kung saan ang hindi nababagong data tungkol sa lahat ng taya at ang oras kung kailan ginawa ang mga ito ay magiging available sa lahat ng kalahok.

Sa Waves blockchain, maaaring maitala ang mga bid sa estado ng auction account sa pamamagitan ng DataTransaction.

Maaari mo ring itakda ang oras ng pagsisimula at pagtatapos ng auction gamit ang mga block number: ang dalas ng pagbuo ng block sa Waves blockchain ay humigit-kumulang katumbas ng 60 segundo.

1. English ascending price auction

Ang mga kalahok sa isang English auction ay naglalagay ng mga bid sa kompetisyon sa isa't isa. Ang bawat bagong taya ay dapat lumampas sa nauna. Nagtatapos ang auction kapag wala nang mga bidder na lalampas sa huling bid. Sa kasong ito, ang pinakamataas na bidder ay dapat magbigay ng nakasaad na halaga.

Mayroon ding opsyon sa auction kung saan nagtatakda ang nagbebenta ng pinakamababang presyo para sa lote, at ang huling presyo ay dapat lumampas dito. Kung hindi, ang lote ay nananatiling hindi nabebenta.

Sa halimbawang ito, nagtatrabaho kami sa isang account na partikular na ginawa para sa auction. Ang tagal ng auction ay 3000 blocks, at ang panimulang presyo ng lot ay 0,001 WAVES. Ang isang kalahok ay maaaring maglagay ng bid sa pamamagitan ng pagpapadala ng DataTransaction na may pangunahing "presyo" at ang halaga ng kanilang bid.

Ang presyo ng bagong bid ay dapat na mas mataas kaysa sa kasalukuyang presyo para sa key na ito, at ang kalahok ay dapat magkaroon ng kahit man lang [new_bid + commission] na mga token sa kanyang account. Ang address ng bidder ay dapat na naitala sa field na "nagpadala" sa DataTransaction, at ang kasalukuyang taas ng block ng bid ay dapat nasa loob ng panahon ng auction.

Kung sa dulo ng auction ang kalahok ay nagtakda ng pinakamataas na presyo, maaari siyang magpadala ng ExchangeTransaction upang magbayad para sa kaukulang lote sa tinukoy na presyo at pares ng pera.

let startHeight = 384120
let finishHeight = startHeight + 3000
let startPrice = 100000
 
#ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ адрСс отправитСля
let this = extract(tx.sender)
let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
 
match tx {
case d : DataTransaction =>
  #провСряСм, Π·Π°Π΄Π°Π½Π° Π»ΠΈ Π² стСйтС Ρ†Π΅Π½Π°
  let currentPrice = if isDefined(getInteger(this, "price"))
 
                      #ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ Ρ†Π΅Π½Ρƒ ΠΈΠ· стСйта
                      then extract(getInteger(this, "price"))
                      else startPrice
 
  #ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ Ρ†Π΅Π½Ρƒ ΠΈΠ· Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ
  let newPrice = extract(getInteger(d.data, "price"))
  let priceIsBigger = newPrice > currentPrice
  let fee = 700000
  let hasMoney = wavesBalance(tx.sender) + fee >= newPrice
 
  #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Π΄Π²Π° поля ΠΈ Ρ‡Ρ‚ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ совпадаСт с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ Π² Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ
  let correctFields = size(d.data) == 2 &&      
      d.sender == addressFromString(extract(getString(d.data,"sender")))
  startHeight <= height && height <= finishHeight && priceIsBigger && hasMoney && correctFields
case e : ExchangeTransaction =>
  let senderIsWinner = e.sender == addressFromString(extract(getString(this, "sender"))) #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π»ΠΎΡ‚ ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°Π΅Ρ‚ Ρ‚ΠΎΡ‚, ΠΊΡ‚ΠΎ Π΅Π³ΠΎ Π²Ρ‹ΠΈΠ³Ρ€Π°Π»
  let correctAssetPair = e.sellOrder.assetPair.amountAsset == token && ! isDefined(e.sellOrder.assetPair.priceAsset)
  let correctAmount = e.amount == 1
  let correctPrice = e.price == extract(getInteger(this, "price"))
 
  height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice
case _ => false
}

2. Dutch auction ng papababang presyo

Sa isang Dutch auction, marami ang unang inaalok sa presyong mas mataas kaysa sa kung ano ang gustong bayaran ng mamimili. Bumababa ang presyo nang hakbang-hakbang hanggang sa pumayag ang isa sa mga kalahok na bilhin ang lote sa kasalukuyang presyo.

Sa halimbawang ito ginagamit namin ang parehong mga constant tulad ng sa nauna, pati na rin ang hakbang ng presyo kapag bumababa ang delta. Sinusuri ng script ng account kung ang kalahok nga ang unang tumaya. Kung hindi, ang DataTransaction ay hindi tinatanggap ng blockchain.

let startHeight = 384120
let finishHeight = startHeight + 3000
let startPrice = 100000000
let delta = 100
 
#ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ адрСс отправитСля
let this = extract(tx.sender)
let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
match tx {
case d : DataTransaction =>
  let currentPrice = startPrice - delta * (height - startHeight)
 
  #ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· ΠΏΠΎΡΡ‚ΡƒΠΏΠΈΠ²ΡˆΠ΅ΠΉ Π΄Π°Ρ‚Π°-Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΏΠΎΠ»Π΅ "price"
  let newPrice = extract(getInteger(d.data, "price"))
 
  #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π² стСйтС Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π° Π½Π΅ содСрТится поля "sender"
  let noBetsBefore = !isDefined(getInteger(this, "sender"))
  let fee = 700000
  let hasMoney = wavesBalance(tx.sender) + fee >= newPrice
 
  #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π²Π° поля
  let correctFields = size(d.data) == 2 && newPrice == currentPrice && d.sender == addressFromString(extract(getString(d.data, "sender")))
  startHeight <= height && height <= finishHeight && noBetsBefore && hasMoney && correctFields
case e : ExchangeTransaction =>
 
  #убСТдаСмся, Ρ‡Ρ‚ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΡƒΠΊΠ°Π·Π°Π½ Π² стСйтС Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π° ΠΏΠΎ ΠΊΠ»ΡŽΡ‡Ρƒ sender
  let senderIsWinner = e.sender == addressFromString(extract(getString(this, "sender")))
 
  #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π°mount ассСта ΡƒΠΊΠ°Π·Π°Π½ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ, ΠΈ Ρ‡Ρ‚ΠΎ прайс-ассСт - waves
  let correctAssetPair = e.sellOrder.assetPair.amountAsset == token && ! isDefined(e.sellOrder.assetPair.priceAsset)
  let correctAmount = e.amount == 1
  let correctPrice = e.price == extract(getInteger(this, "price"))
  height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice
case _ => false
}

3. Auction na "all-pay"

Ang "All-pay" ay isang auction kung saan ang lahat ng kalahok ay nagbabayad ng bid, hindi alintana kung sino ang nanalo sa lot. Bawat bagong kalahok ay magbabayad ng bid, at ang kalahok na gumawa ng pinakamataas na bid ang mananalo sa lot.

Sa aming halimbawa, ang bawat kalahok sa auction ay naglalagay ng bid sa pamamagitan ng DataTransaction na may (key, value)* = (β€œwinner”, address),(β€œprice”, price). Ang nasabing DataTransaction ay naaprubahan lamang kung ang kalahok na ito ay mayroon nang isang TransferTransaction na may kanyang pirma at ang kanyang bid ay mas mataas kaysa sa lahat ng nauna. Nagpapatuloy ang auction hanggang sa maabot ang endHeight.

let startHeight = 1000
let endHeight = 2000
let this = extract(tx.sender)
let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
match tx {
 case d: DataTransaction =>
   #ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· ΠΏΠΎΡΡ‚ΡƒΠΏΠΈΠ²ΡˆΠ΅ΠΉ Π΄Π°Ρ‚Π°-Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΏΠΎΠ»Π΅ "price"
   let newPrice = extract(getInteger(d.data, "price"))
 
   #ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· ΠΏΡ€ΡƒΡ„ΠΎΠ² Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹ΠΉ ΠΊΠ»ΡŽΡ‡ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π°
   let pk = d.proofs[1]
   let address = addressFromPublicKey(pk)
 
   #ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ Π΄ΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒΡΡ‚Π²ΠΎ ΠΈΠ· ΠΏΡ€ΡƒΡ„ΠΎΠ² ΠΏΠΎΡΡ‚ΡƒΠΏΠΈΠ²ΡˆΠ΅ΠΉ Π΄Π°Ρ‚Π° Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ
   let proofTx = extract(transactionById(d.proofs[2]))
   
   height > startHeight && height < endHeight
   && size(d.data) == 2
   #убСТдаСмся, Ρ‡Ρ‚ΠΎ адрСс побСдитСля, ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½Π½Ρ‹ΠΉ ΠΈΠ· Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, совпадаСт с адрСсом, ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½Π½Ρ‹ΠΌ ΠΈΠ· ΠΏΡ€ΡƒΡ„ΠΎΠ²
   && extract(getString(d.data, "winner")) == toBase58String(address.bytes)
   && newPrice > extract(getInteger(this, "price"))
   #провСряСм, Ρ‡Ρ‚ΠΎ транзакция подписана
   && sigVerify(d.bodyBytes, d.proofs[0], d.proofs[1])
   #провСряСм ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π² ΠΏΡ€ΡƒΡ„Π°Ρ…
   && match proofTx {
     case tr : TransferTransaction =>
       tr.sender == address &&
       tr.amount == newPrice
     case _ => false
   }
 case t: TransferTransaction =>
 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
 || (
   height > endHeight
   && extract(getString(this, "winner")) == toBase58String((addressFromRecipient(t.recipient)).bytes)
   && t.assetId == token
   && t.amount == 1
 )
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Insurance / Crowdfunding

Isaalang-alang natin ang isang sitwasyon kung saan kailangan mong iseguro ang mga asset ng mga user laban sa mga pagkalugi sa pananalapi. Halimbawa, gusto ng isang user ng garantiya na kung bumaba ang halaga ng isang token, mababawi niya ang buong halagang binayaran para sa mga token na ito, at handang magbayad ng makatwirang halaga ng insurance.

Upang maipatupad ito, kailangang maibigay ang "mga token ng insurance". Pagkatapos ay may na-install na script sa account ng may-ari ng patakaran, na nagpapahintulot lamang sa mga ExchangeTransaction na nakakatugon sa ilang partikular na kundisyon na maisagawa.

Upang maiwasan ang dobleng paggastos, kailangan mong hilingin sa user na magpadala ng DataTransaction sa account ng policyholder nang maaga gamit ang (key, value) = (purchaseTransactionId, sellOrderId) at ipagbawal ang pagpapadala ng DataTransactions gamit ang isang key na nagamit na.

Samakatuwid, ang mga patunay ng user ay dapat maglaman ng transaction ID ng pagbili ng token ng insurance. Ang pares ng pera ay dapat na kapareho ng sa transaksyon sa pagbili. Ang gastos ay dapat ding katumbas ng naayos sa oras ng pagbili, ibinawas ang presyo ng insurance.

Nauunawaan na pagkatapos ay bumili ang insurance account ng mga insurance token mula sa user sa presyong hindi mas mababa kaysa sa kung saan niya binili ang mga ito: ang insurance account ay lumilikha ng ExchangeTransaction, pinirmahan ng user ang order (kung nakumpleto nang tama ang transaksyon), ang nilalagdaan ng insurance account ang pangalawang order at ang buong transaksyon at ipinapadala ito sa blockchain.

Kung walang pagbili na nangyari, ang user ay maaaring gumawa ng ExchangeTransaction ayon sa mga panuntunang inilarawan sa script at ipadala ang transaksyon sa blockchain. Sa ganitong paraan maibabalik ng user ang perang ginastos sa pagbili ng mga naka-insured na token.

let insuranceToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
 
#ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ адрСс отправитСля
let this = extract(tx.sender)
let freezePeriod = 150000
let insurancePrice = 10000
match tx {
 
 #убСТдаСмся, Ρ‡Ρ‚ΠΎ, Ссли поступила Π΄Π°Ρ‚Π°-транзакция, Ρ‚ΠΎ Ρƒ Π½Π΅Π΅ Ρ€ΠΎΠ²Π½ΠΎ ΠΎΠ΄Π½ΠΎ ΠΏΠΎΠ»Π΅ ΠΈ Π² стСйтС Π΅Ρ‰Π΅ Π½Π΅Ρ‚ Ρ‚Π°ΠΊΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π°
 case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key))
 case e : ExchangeTransaction =>
 
   #Ссли Ρƒ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Π½Π΅Ρ‚ сСдьмого ΠΏΡ€ΡƒΡ„Π°, провСряСм ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ подписи
   if !isDefined(e.proofs[7]) then
     sigVerify(e.bodyBytes, e.proofs[0], e.senderPublicKey)
   else
     #Ссли Ρƒ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Π΅ΡΡ‚ΡŒ сСдьмой ΠΏΡ€ΡƒΡ„, ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· Π½Π΅Π³ΠΎ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ ΠΈ ΡƒΠ·Π½Π°Ρ‘ΠΌ Π΅Ρ‘ высоту
     let purchaseTx = transactionById(e.proofs[7])
     let purchaseTxHeight = extract(transactionHeightById(e.proofs[7]))
    
     #ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ ΠΈΠ· ΠΏΡ€ΡƒΡ„Π°
     match purchaseTx {
       case purchase : ExchangeTransaction =>
         let correctSender = purchase.sender == e.sellOrder.sender
         let correctAssetPair = e.sellOrder.assetPair.amountAsset == insuranceToken &&
                                purchase.sellOrder.assetPair.amountAsset == insuranceToken &&
                                e.sellOrder.assetPair.priceAsset == purchase.sellOrder.assetPair.priceAsset
         let correctPrice = e.price == purchase.price - insurancePrice && e.amount == purchase.amount
         let correctHeight = height > purchaseTxHeight + freezePeriod
 
         #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π² Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ-ΠΏΡ€ΡƒΡ„Π΅ ΡƒΠΊΠ°Π·Π°Π½ Π²Π΅Ρ€Π½Ρ‹ΠΉ ID Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ
         let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == e.sellOrder.id
         correctSender && correctAssetPair && correctPrice && correctHeight && correctProof
     case _ => false
   }
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Ang isang insurance token ay maaaring gawing matalinong asset, halimbawa, upang ipagbawal ang paglipat nito sa mga third party.

Ang scheme na ito ay maaari ding ipatupad para sa mga token ng crowdfunding, na ibinabalik sa mga may-ari kung ang kinakailangang halaga ay hindi pa nakolekta.

Mga buwis sa transaksyon

Naaangkop din ang mga smart contract sa mga kaso kung saan kinakailangang mangolekta ng buwis sa bawat transaksyon na may ilang uri ng asset. Magagawa ito sa pamamagitan ng isang bagong asset na may naka-install sponsorship para sa mga transaksyong may mga matalinong asset:

1. Nag-isyu kami ng FeeCoin, na ipapadala sa mga user sa isang nakapirming presyo: 0,01 WAVES = 0,001 FeeCoin.

2. Itakda ang sponsorship para sa FeeCoin at exchange rate: 0,001 WAVES = 0,001 FeeCoin.

3. Itakda ang sumusunod na script para sa smart asset:

let feeAssetId = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
let taxDivisor = 10
 
match tx {
  case t: TransferTransaction =>
    t.feeAssetId == feeAssetId && t.fee == t.amount / taxDivisor
  case e: ExchangeTransaction | MassTransferTransaction => false
  case _ => true
}

Ngayon sa tuwing may maglilipat ng N smart asset, bibigyan ka nila ng FeeCoin sa halagang N/taxDivisor (na mabibili mula sa iyo sa 10 *N/taxDivisor WAVES), at bibigyan mo ang minero ng N/taxDivisor WAVES. Bilang resulta, ang iyong tubo (buwis) ay magiging 9*N / taxDivisor WAVES.

Maaari ka ring magsagawa ng pagbubuwis gamit ang isang smart asset script at MassTransferTransaction:

let taxDivisor = 10
 
match tx {
  case t : MassTransferTransaction =>
    let twoTransfers = size(t.transfers) == 2
    let issuerIsRecipient = t.transfers[0].recipient == addressFromString("3MgkTXzD72BTfYpd9UW42wdqTVg8HqnXEfc")
    let taxesPaid = t.transfers[0].amount >= t.transfers[1].amount / taxDivisor
    twoTransfers && issuerIsRecipient && taxesPaid
  case _ => false
}

Cashback at mga programa ng katapatan

Ang cashback ay isang uri ng loyalty program kung saan ibinabalik ng mamimili ang bahagi ng halagang ginastos sa isang produkto o serbisyo.

Kapag ipinatupad ang kasong ito gamit ang isang matalinong account, dapat nating suriin ang mga patunay sa parehong paraan tulad ng ginawa natin sa kaso ng insurance. Upang maiwasan ang dobleng paggastos, dapat magpadala ang user ng DataTransaction na may (key, value) = (purchaseTransactionId, cashbackTransactionId) bago makatanggap ng cashback.

Dapat din tayong magtakda ng pagbabawal sa mga umiiral nang key gamit ang DataTransaction. cashbackDivisor - yunit na hinati sa bahagi ng cashback. Yung. kung ang bahagi ng cashback ay 0.1, pagkatapos ay ang cashbackDivisor 1 / 0.1 = 10.

let cashbackToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
 
#ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ адрСс отправитСля
let this = extract(tx.sender)
let cashbackDivisor = 10
match tx {
 
 #убСТдаСмся, Ρ‡Ρ‚ΠΎ, Ссли поступила Π΄Π°Ρ‚Π°-транзакция, Ρ‚ΠΎ Ρƒ Π½Π΅Π΅ Ρ€ΠΎΠ²Π½ΠΎ ΠΎΠ΄Π½ΠΎ ΠΏΠΎΠ»Π΅ ΠΈ Π² стСйтС Π΅Ρ‰Π΅ Π½Π΅Ρ‚ Ρ‚Π°ΠΊΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π°
 case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key))
 case e : TransferTransaction =>
 
   #Ссли Ρƒ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Π½Π΅Ρ‚ сСдьмого ΠΏΡ€ΡƒΡ„Π°, провСряСм ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ подписи
   if !isDefined(e.proofs[7]) then
     sigVerify(e.bodyBytes, e.proofs[0], e.senderPublicKey)
   else
 
     #Ссли Ρƒ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Π΅ΡΡ‚ΡŒ сСдьмой ΠΏΡ€ΡƒΡ„, ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ ΠΈΠ· Π½Π΅Π³ΠΎ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ ΠΈ ΡƒΠ·Π½Π°Ρ‘ΠΌ Π΅Ρ‘ высоту
     let purchaseTx = transactionById(e.proofs[7])
     let purchaseTxHeight = extract(transactionHeightById(e.proofs[7]))
    
     #ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ ΠΈΠ· ΠΏΡ€ΡƒΡ„Π°
     match purchaseTx {
       case purchase : TransferTransaction =>
         let correctSender = purchase.sender == e.sender
         let correctAsset = e.assetId == cashbackToken
         let correctPrice = e.amount == purchase.amount / cashbackDivisor
 
         #убСТдаСмся, Ρ‡Ρ‚ΠΎ Π² Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ-ΠΏΡ€ΡƒΡ„Π΅ ΡƒΠΊΠ°Π·Π°Π½ Π²Π΅Ρ€Π½Ρ‹ΠΉ ID Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ
         let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == e.id
         correctSender && correctAsset && correctPrice && correctProof
     case _ => false
   }
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Atomic swap

Nagbibigay-daan ang Atomic swap sa mga user na makipagpalitan ng mga asset nang walang tulong ng isang exchange. Sa pamamagitan ng isang atomic swap, ang parehong mga kalahok sa transaksyon ay kinakailangan upang kumpirmahin ito sa loob ng isang tiyak na tagal ng panahon.

Kung hindi bababa sa isa sa mga kalahok ang hindi nagbibigay ng tamang kumpirmasyon ng transaksyon sa loob ng oras na inilaan para sa transaksyon, ang transaksyon ay kinansela at ang palitan ay hindi mangyayari.

Sa aming halimbawa, gagamitin namin ang sumusunod na script ng smart account:

let Bob = Address(base58'3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8')
let Alice = Address(base58'3PNX6XwMeEXaaP1rf5MCk8weYeF7z2vJZBg')
 
let beforeHeight = 100000
 
let secret = base58'BN6RTYGWcwektQfSFzH8raYo9awaLgQ7pLyWLQY4S4F5'
match tx {
  case t: TransferTransaction =>
    let txToBob = t.recipient == Bob && sha256(t.proofs[0]) == secret && 20 + beforeHeight >= height
    let backToAliceAfterHeight = height >= 21 + beforeHeight && t.recipient == Alice
    txToBob || backToAliceAfterHeight
  case _ => false
}

Sa susunod na artikulo titingnan natin ang paggamit ng mga matalinong account sa mga instrumento sa pananalapi tulad ng mga opsyon, futures at mga bill.

Pinagmulan: www.habr.com

Magdagdag ng komento