Applikazzjoni ta 'kontijiet intelliġenti Waves: minn irkanti għal programmi ta' bonus

Applikazzjoni ta 'kontijiet intelliġenti Waves: minn irkanti għal programmi ta' bonus

Blockchain ħafna drabi huwa assoċjat biss mal-kripto-muniti, iżda l-oqsma ta 'applikazzjoni tat-teknoloġija DLT huma ħafna usa'. Wieħed mill-oqsma l-aktar promettenti għall-użu tal-blockchain huwa kuntratt intelliġenti li jiġi esegwit awtomatikament u ma jeħtieġx fiduċja bejn il-partijiet li daħlu fih.

RIDE – lingwa għal kuntratti intelliġenti

Waves żviluppat lingwaġġ speċjali għal kuntratti intelliġenti - RIDE. Id-dokumentazzjoni sħiħa tagħha tinsab hawn. U hawn - artiklu dwar dan is-suġġett fuq Habr.

Il-kuntratt RIDE huwa predikat u jirritorna "veru" jew "falz" bħala output. Għaldaqstant, it-tranżazzjoni jew tiġi rreġistrata fil-blockchain jew miċħuda. Il-kuntratt intelliġenti jiggarantixxi bis-sħiħ it-twettiq ta 'kundizzjonijiet speċifikati. Il-ġenerazzjoni ta' tranżazzjonijiet minn kuntratt f'RIDE bħalissa mhix possibbli.

Illum hemm żewġ tipi ta’ kuntratti intelliġenti Waves: kontijiet intelliġenti u assi intelliġenti. Kont intelliġenti huwa kont ta 'utent regolari, iżda skript huwa stabbilit għalih li jikkontrolla t-tranżazzjonijiet kollha. Skript ta' kont intelliġenti jista' jidher bħal dan, pereżempju:

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

tx hija tranżazzjoni li qed tiġi pproċessata li nippermettu l-użu tal-mekkaniżmu ta' tqabbil tal-mudelli biss jekk ma tkunx tranżazzjoni ta' trasferiment. It-tqabbil tal-mudelli f'RIDE jintuża biex jiċċekkja t-tip ta' tranżazzjoni. Il-kontijiet eżistenti kollha jistgħu jiġu pproċessati fl-iskript tal-kont intelliġenti tipi ta' tranżazzjonijiet.

L-iskript jista 'wkoll jiddikjara varjabbli, juża kostruzzjonijiet "jekk imbagħad inkella" u metodi oħra għall-iċċekkjar sħiħ tal-kundizzjonijiet. Biex jiġi żgurat li l-kuntratti jkollhom kompletezza u kumplessità (kost) li tista' tiġi ppruvata li hija faċli biex titbassar qabel ma tibda l-eżekuzzjoni tal-kuntratt, RIDE ma fihx loops jew dikjarazzjonijiet jaqbżu.

Karatteristiċi oħra tal-kontijiet Waves jinkludu l-preżenza ta '"stat", jiġifieri, l-istat tal-kont. Tista 'tikteb numru infinit ta' pari (ċavetta, valur) fl-istat tal-kont billi tuża transazzjonijiet tad-dejta (DataTransaction). Din l-informazzjoni mbagħad tista 'tiġi pproċessata kemm permezz tal-API REST kif ukoll direttament fil-kuntratt intelliġenti.

Kull tranżazzjoni jista' jkun fiha firxa ta' provi, li fihom tista' tiddaħħal il-firma tal-parteċipant, l-ID tat-tranżazzjoni meħtieġa, eċċ.

Ħidma ma 'RIDE via IDE jippermettilek tara d-dehra kkompilata tal-kuntratt (jekk ikun ikkumpilat), toħloq kontijiet ġodda u tistabbilixxi skripts għaliha, kif ukoll tibgħat transazzjonijiet permezz tal-linja tal-kmand.

Għal ċiklu sħiħ, inkluż il-ħolqien ta 'kont, l-installazzjoni ta' kuntratt intelliġenti fuqu u tibgħat tranżazzjonijiet, tista 'wkoll tuża librerija għall-interazzjoni mal-API REST (per eżempju, C#, C, Java, JavaScript, Python, Rust, Elixir) . Biex tibda taħdem bl-IDE, ikklikkja l-buttuna ĠODDA.

Il-possibbiltajiet għall-użu ta 'kuntratti intelliġenti huma wiesgħa: mill-projbizzjoni ta' tranżazzjonijiet għal ċerti indirizzi ("lista sewda") għal dApps kumplessi.

Issa ejja nħarsu lejn eżempji speċifiċi tal-użu ta 'kuntratti intelliġenti fin-negozju: meta twettaq irkanti, assigurazzjoni, u toħloq programmi ta' lealtà.

Irkanti

Waħda mill-kundizzjonijiet għal irkant ta' suċċess hija t-trasparenza: il-parteċipanti jridu jkunu kunfidenti li huwa impossibbli li jiġu mmanipulati l-offerti. Dan jista 'jinkiseb grazzi għall-blockchain, fejn dejta immutabbli dwar l-imħatri kollha u l-ħin meta saru se tkun disponibbli għall-parteċipanti kollha.

Fuq il-blockchain Waves, l-offerti jistgħu jiġu rreġistrati fl-istat tal-kont tal-irkant permezz tad-DataTransaction.

Tista' wkoll tissettja l-ħin tal-bidu u t-tmiem tal-irkant billi tuża numri tal-blokki: il-frekwenza tal-ġenerazzjoni tal-blokki fil-blockchain Waves hija bejn wieħed u ieħor ugwali għal 60 sekondi.

1. Irkant bil-prezz axxendenti bl-Ingliż

Parteċipanti f'irkant bl-Ingliż jagħmlu offerti f'kompetizzjoni ma' xulxin. Kull mħatra ġdida trid taqbeż dik preċedenti. L-irkant jintemm meta ma jkunx hemm aktar offerenti li jaqbżu l-aħħar offerta. F'dan il-każ, l-ogħla offerent għandu jipprovdi l-ammont iddikjarat.

Hemm ukoll għażla ta 'rkant li fiha l-bejjiegħ jiffissa prezz minimu għall-lott, u l-prezz finali għandu jaqbeż. Inkella, il-lott jibqa 'mhux mibjugħ.

F'dan l-eżempju, qed naħdmu b'kont maħluq speċifikament għall-irkant. It-tul tal-irkant huwa 3000 blokka, u l-prezz tal-bidu tal-lott huwa 0,001 WAVES. Parteċipant jista’ jagħmel offerta billi jibgħat DataTransaction bil-“prezz” ewlieni u l-valur tal-offerta tiegħu.

Il-prezz tal-offerta l-ġdida għandu jkun ogħla mill-prezz attwali għal din iċ-ċavetta, u l-parteċipant irid ikollu mill-inqas [new_bid + commission] tokens fil-kont tiegħu. L-indirizz tal-offerent għandu jiġi rreġistrat fil-qasam "mittent" fid-DataTransaction, u l-għoli attwali tal-blokka tal-offerta għandu jkun fil-perjodu tal-irkant.

Jekk fl-aħħar tal-irkant il-parteċipant stabbilixxa l-ogħla prezz, huwa jista 'jibgħat ExchangeTransaction biex iħallas għal-lott korrispondenti bil-prezz speċifikat u l-par ta' muniti.

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. Irkant Olandiż ta' prezzijiet li qed jonqsu

F'irkant Olandiż, inizjalment ħafna jiġi offrut bi prezz ogħla minn dak li x-xerrej ikun lest li jħallas. Il-prezz jonqos pass pass sakemm wieħed mill-parteċipanti jaqbel li jixtri l-lott bil-prezz attwali.

F'dan l-eżempju nużaw l-istess kostanti bħal ta 'qabel, kif ukoll il-pass tal-prezz meta delta tonqos. L-iskrittura tal-kont jiċċekkja jekk il-parteċipant huwiex tabilħaqq l-ewwel li jpoġġi mħatra. Inkella, id-DataTransaction mhix aċċettata mill-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. Irkant “paga kollha”

"All-pay" huwa irkant li fih il-parteċipanti kollha jħallsu l-offerta, irrispettivament minn min jirbaħ il-lott. Kull parteċipant ġdid iħallas offerta, u l-parteċipant li jagħmel l-offerta massima jirbaħ il-lott.

Fl-eżempju tagħna, kull parteċipant tal-irkant jagħmel offerta permezz tad-DataTransaction bi (ċavetta, valur)* = ("rebbieħ", indirizz), ("prezz", prezz). Tali DataTransaction tiġi approvata biss jekk dan il-parteċipant diġà jkollu TransferTransaction bil-firma tiegħu u l-offerta tiegħu tkun ogħla minn dawk kollha preċedenti. L-irkant ikompli sakemm tintlaħaq l-Għoli tat-tmiem.

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)
}

Assigurazzjoni / Crowdfunding

Ejja nikkunsidraw sitwazzjoni fejn għandek bżonn tassigura l-assi tal-utenti kontra telf finanzjarju. Pereżempju, utent irid garanzija li jekk token jiddeprezza, ikun jista 'jiġi lura l-ammont sħiħ imħallas għal dawn it-tokens, u jkun lest li jħallas ammont raġonevoli ta' assigurazzjoni.

Biex timplimenta dan, jeħtieġ li jinħarġu "tokens tal-assigurazzjoni". Imbagħad skript jiġi installat fuq il-kont tad-detentur tal-polza, li jippermetti biss li jiġu eżegwiti dawk it-Transazzjonijiet ta’ Skambju li jissodisfaw ċerti kundizzjonijiet.

Biex tipprevjeni nfiq doppju, trid titlob lill-utent biex jibgħat DataTransaction lill-kont tad-detentur tal-polza bil-quddiem bi (ċavetta, valur) = (purchaseTransactionId, sellOrderId) u tipprojbixxi li tibgħat DataTransactions b'ċavetta li tkun diġà ntużat.

Għalhekk, il-provi tal-utent għandu jkun fihom l-ID tat-tranżazzjoni tax-xiri tat-token tal-assigurazzjoni. Il-par tal-muniti għandu jkun l-istess bħal fit-tranżazzjoni tax-xiri. L-ispiża għandha wkoll tkun ugwali għal dik iffissata fil-ħin tax-xiri, nieqes il-prezz tal-assigurazzjoni.

Huwa mifhum li sussegwentement il-kont tal-assigurazzjoni jixtri tokens tal-assigurazzjoni mingħand l-utent bi prezz mhux inqas minn dak li bih xtarahom: il-kont tal-assigurazzjoni joħloq ExchangeTransaction, l-utent jiffirma l-ordni (jekk it-tranżazzjoni titlesta b'mod korrett), il- kont tal-assigurazzjoni jiffirma t-tieni ordni u t-tranżazzjoni kollha u jibgħatha lill-blockchain.

Jekk ma jseħħ l-ebda xiri, l-utent jista 'joħloq ExchangeTransaction skond ir-regoli deskritti fl-iskrittura u jibgħat it-tranżazzjoni lill-blockchain. B'dan il-mod l-utent jista 'jirritorna l-flus minfuqa fuq ix-xiri ta' tokens assigurati.

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)
}

Token tal-assigurazzjoni jista 'jsir assi intelliġenti, pereżempju, biex jipprojbixxi t-trasferiment tiegħu lil partijiet terzi.

Din l-iskema tista 'tiġi implimentata wkoll għal tokens ta' finanzjament kollettiv, li jintbagħtu lura lis-sidien jekk l-ammont meħtieġ ma jkunx inġabar.

Taxxi fuq it-transazzjonijiet

Kuntratti intelliġenti huma applikabbli wkoll f'każijiet fejn ikun meħtieġ li tinġabar taxxa fuq kull tranżazzjoni b'diversi tipi ta' assi. Dan jista 'jsir permezz ta' assi ġdid ma installat sponsorizzazzjoni għal tranżazzjonijiet b'assi intelliġenti:

1. Aħna noħorġu FeeCoin, li se jintbagħat lill-utenti bi prezz fiss: 0,01 WAVES = 0,001 FeeCoin.

2. Issettja l-isponsorizzazzjoni għal FeeCoin u r-rata tal-kambju: 0,001 WAVES = 0,001 FeeCoin.

3. Issettja l-iskript li ġej għall-assi intelliġenti:

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
}

Issa kull darba li xi ħadd jittrasferixxi N assi intelliġenti, jagħtik FeeCoin fl-ammont ta 'N/taxDivisor (li jista' jinxtara mingħandek f'10 *N/taxDivisor WAVES), u inti tagħti lill-minatur N/taxDivisor WAVES. Bħala riżultat, il-profitt tiegħek (taxxa) se jkun 9*N / taxDivisor WAVES.

Tista 'wkoll twettaq tassazzjoni billi tuża script ta' assi intelliġenti u 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 u programmi ta' lealtà

Cashback huwa tip ta’ programm ta’ lealtà li fih ix-xerrej jieħu lura parti mill-ammont minfuq fuq prodott jew servizz.

Meta nimplimentaw dan il-każ billi tuża kont intelliġenti, irridu niċċekkjaw il-provi bl-istess mod kif għamilna fil-każ tal-assigurazzjoni. Biex jipprevjeni nfiq doppju, l-utent irid jibgħat DataTransaction bi (ċavetta, valur) = (purchaseTransactionId, cashbackTransactionId) qabel ma jirċievi cashback.

Irridu wkoll nistabbilixxu projbizzjoni fuq iċ-ċwievet eżistenti bl-użu ta 'DataTransaction. cashbackDivisor - unità diviża bis-sehem tal-cashback. Dawk. jekk is-sehem tal-cashback huwa 0.1, allura 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)
}

Skambju atomiku

L-iskambju atomiku jippermetti lill-utenti jiskambjaw assi mingħajr l-għajnuna ta 'skambju. Bi tpartit atomiku, iż-żewġ parteċipanti fit-tranżazzjoni huma meħtieġa jikkonfermawha f'ċertu perjodu ta 'żmien.

Jekk mill-inqas wieħed mill-parteċipanti ma jipprovdix konferma korretta tat-tranżazzjoni fiż-żmien allokat għat-tranżazzjoni, it-tranżazzjoni tiġi kkanċellata u l-iskambju ma jseħħx.

Fl-eżempju tagħna, se nużaw l-iskript tal-kont intelliġenti li ġej:

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
}

Fl-artiklu li jmiss se nħarsu lejn l-użu ta’ kontijiet intelliġenti fi strumenti finanzjarji bħal għażliet, futures u kontijiet.

Sors: www.habr.com

Żid kumment