Cymhwyso cyfrifon smart Waves: o arwerthiannau i raglenni bonws

Cymhwyso cyfrifon smart Waves: o arwerthiannau i raglenni bonws

Mae Blockchain yn aml yn gysylltiedig â cryptocurrencies yn unig, ond mae meysydd cymhwyso technoleg DLT yn llawer ehangach. Un o'r meysydd mwyaf addawol ar gyfer defnyddio blockchain yw contract smart sy'n cael ei weithredu'n awtomatig ac nid oes angen ymddiriedaeth rhwng y partïon a ymrwymodd iddo.

RIDE - iaith ar gyfer contractau smart

Mae Waves wedi datblygu iaith arbennig ar gyfer contractau smart - RIDE. Mae ei ddogfennaeth gyflawn wedi'i lleoli yma. Ac yma - erthygl ar y pwnc hwn ar Habr.

Mae contract RIDE yn rhagfynegiad ac yn dychwelyd “gwir” neu “anghywir” fel allbwn. Yn unol â hynny, mae'r trafodiad naill ai'n cael ei gofnodi yn y blockchain neu ei wrthod. Mae'r contract smart yn gwarantu cyflawni amodau penodol yn llawn. Nid yw'n bosibl cynhyrchu trafodion o gontract yn RIDE ar hyn o bryd.

Heddiw mae dau fath o gontractau smart Waves: cyfrifon smart ac asedau smart. Mae cyfrif smart yn gyfrif defnyddiwr rheolaidd, ond mae sgript wedi'i osod ar ei gyfer sy'n rheoli'r holl drafodion. Gallai sgript cyfrif clyfar edrych fel hyn, er enghraifft:

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

Mae tx yn drafodiad sy'n cael ei brosesu yr ydym yn ei ganiatáu gan ddefnyddio'r mecanwaith paru patrymau dim ond os nad yw'n drafodiad trosglwyddo. Defnyddir paru patrymau yn RIDE i wirio'r math o drafodiad. Gellir prosesu'r holl gyfrifon presennol yn y sgript cyfrif clyfar mathau o drafodion.

Gall y sgript hefyd ddatgan newidynnau, defnyddio lluniadau “os-yna-arall” a dulliau eraill ar gyfer gwirio amodau'n llawn. Er mwyn sicrhau bod gan gontractau gyflawnder a chymhlethdod profadwy (cost) sy'n hawdd eu rhagweld cyn i'r contract ddechrau, nid yw RIDE yn cynnwys dolenni na datganiadau naid.

Mae nodweddion eraill cyfrifon Waves yn cynnwys presenoldeb “cyflwr,” hynny yw, cyflwr y cyfrif. Gallwch ysgrifennu nifer anfeidrol o barau (allwedd, gwerth) i gyflwr y cyfrif gan ddefnyddio trafodion data (DataTransaction). Yna gellir prosesu'r wybodaeth hon trwy'r API REST ac yn uniongyrchol yn y contract smart.

Gall pob trafodiad gynnwys amrywiaeth o broflenni, lle gellir nodi llofnod y cyfranogwr, ID y trafodiad gofynnol, ac ati.

Gweithio gyda RIDE drwy IDE yn eich galluogi i weld yr olwg a luniwyd o'r contract (os caiff ei lunio), creu cyfrifon newydd a gosod sgriptiau ar ei gyfer, yn ogystal ag anfon trafodion trwy'r llinell orchymyn.

Am gylchred lawn, gan gynnwys creu cyfrif, gosod contract smart arno ac anfon trafodion, gallwch hefyd ddefnyddio llyfrgell ar gyfer rhyngweithio â'r API REST (er enghraifft, C#, C, Java, JavaScript, Python, Rust, Elixir) . I ddechrau gweithio gyda'r DRhA, cliciwch ar y botwm NEWYDD.

Mae'r posibiliadau ar gyfer defnyddio contractau smart yn eang: o wahardd trafodion i rai cyfeiriadau (“rhestr ddu”) i dApps cymhleth.

Nawr, gadewch i ni edrych ar enghreifftiau penodol o'r defnydd o gontractau smart mewn busnes: wrth gynnal arwerthiannau, yswiriant, a chreu rhaglenni teyrngarwch.

Arwerthiannau

Un o'r amodau ar gyfer arwerthiant llwyddiannus yw tryloywder: rhaid i gyfranogwyr fod yn hyderus ei bod yn amhosibl trin cynigion. Gellir cyflawni hyn diolch i'r blockchain, lle bydd data na ellir ei gyfnewid am yr holl betiau a'r amser y cawsant eu gwneud ar gael i'r holl gyfranogwyr.

Ar y blockchain Waves, gellir cofnodi cynigion yn y cyflwr cyfrif arwerthiant trwy DataTransaction.

Gallwch hefyd osod amser dechrau a gorffen yr arwerthiant gan ddefnyddio rhifau bloc: mae amlder cynhyrchu blociau yn y blockchain Waves fwy neu lai'n hafal i 60 eiliadau.

1. Arwerthiant pris esgynnol Saesneg

Mae cyfranogwyr mewn arwerthiant Saesneg yn gosod cynigion mewn cystadleuaeth â'i gilydd. Rhaid i bob bet newydd fod yn fwy na'r un blaenorol. Daw'r arwerthiant i ben pan nad oes mwy o gynigwyr i ragori ar y cynnig diwethaf. Yn yr achos hwn, rhaid i'r cynigydd uchaf ddarparu'r swm a nodir.

Mae yna hefyd opsiwn arwerthiant lle mae'r gwerthwr yn gosod isafswm pris ar gyfer y lot, a rhaid i'r pris terfynol fod yn fwy na hynny. Fel arall, mae'r lot yn dal heb ei werthu.

Yn yr enghraifft hon, rydym yn gweithio gyda chyfrif a grëwyd yn benodol ar gyfer yr arwerthiant. Hyd yr arwerthiant yw 3000 bloc, a phris cychwynnol y lot yw 0,001 TONNAU. Gall cyfranogwr osod bid trwy anfon Trafodyn Data gyda'r “pris” allweddol a gwerth eu bid.

Rhaid i bris y bid newydd fod yn uwch na'r pris cyfredol ar gyfer yr allwedd hon, a rhaid i'r cyfranogwr gael o leiaf [new_bid + commission] tocynnau yn ei gyfrif. Rhaid cofnodi cyfeiriad y cynigydd yn y maes "anfonwr" yn y DataTransaction, a rhaid i uchder y bloc cynnig presennol fod o fewn y cyfnod arwerthiant.

Os yw'r cyfranogwr wedi gosod y pris uchaf ar ddiwedd yr arwerthiant, gall anfon ExchangeTransaction i dalu am y lot cyfatebol am y pris penodedig a'r pâr arian.

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. Arwerthiant Iseldiroedd o brisiau gostyngol

Mewn arwerthiant yn yr Iseldiroedd, cynigir llawer i ddechrau am bris uwch na'r hyn y mae'r prynwr yn fodlon ei dalu. Mae'r pris yn gostwng gam wrth gam nes bod un o'r cyfranogwyr yn cytuno i brynu'r lot am y pris cyfredol.

Yn yr enghraifft hon rydym yn defnyddio'r un cysonion ag yn yr un blaenorol, yn ogystal â'r cam pris pan fydd delta yn gostwng. Mae sgript y cyfrif yn gwirio ai'r cyfranogwr yn wir yw'r cyntaf i osod bet. Fel arall, ni dderbynnir y DataTransaction gan y 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. Arwerthiant “all-pay”

Mae “All-pay” yn arwerthiant lle mae'r holl gyfranogwyr yn talu'r bid, ni waeth pwy sy'n ennill y lot. Mae pob cyfranogwr newydd yn talu bid, a'r cyfranogwr sy'n gwneud y cynnig mwyaf sy'n ennill y lot.

Yn ein hesiampl, mae pob cyfranogwr arwerthiant yn gosod bid trwy DataTransaction gyda (allwedd, gwerth)* = (“enillydd”, cyfeiriad), (“pris”, pris). Dim ond os oes gan y cyfranogwr hwn eisoes DrosglwyddoTransaction gyda'i lofnod a bod ei gais yn uwch na'r holl rai blaenorol yn cael ei gymeradwyo. Mae'r arwerthiant yn parhau nes cyrraedd 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)
}

Yswiriant / Cyllid Torfol

Gadewch i ni ystyried sefyllfa lle mae angen ichi yswirio asedau defnyddwyr rhag colledion ariannol. Er enghraifft, mae defnyddiwr eisiau gwarant, os bydd tocyn yn dibrisio, y bydd yn gallu cael y swm llawn a dalwyd am y tocynnau hyn yn ôl, ac mae'n fodlon talu swm rhesymol o yswiriant.

Er mwyn gweithredu hyn, mae angen cyhoeddi “tocynnau yswiriant”. Yna gosodir sgript ar gyfrif deiliad y polisi, gan ganiatáu dim ond y Trafodion Cyfnewid hynny sy'n bodloni amodau penodol i gael eu gweithredu.

Er mwyn atal gwariant dwbl, mae angen i chi ofyn i'r defnyddiwr anfon DataTransaction i gyfrif y deiliad polisi ymlaen llaw gyda (allwedd, gwerth) = (purchaseTransactionId, sellOrderId) a gwahardd anfon DataTransaction gydag allwedd sydd eisoes wedi'i defnyddio.

Felly, rhaid i broflenni'r defnyddiwr gynnwys ID trafodiad pryniant tocyn yswiriant. Rhaid i'r pâr arian fod yr un peth ag yn y trafodiad prynu. Rhaid i'r gost hefyd fod yn gyfartal â'r hyn a bennwyd ar adeg prynu, llai pris yswiriant.

Deellir bod y cyfrif yswiriant wedi hynny yn prynu tocynnau yswiriant gan y defnyddiwr am bris nad yw'n is na'r un y prynodd ef: mae'r cyfrif yswiriant yn creu Trafodiad Cyfnewid, mae'r defnyddiwr yn llofnodi'r archeb (os caiff y trafodiad ei gwblhau'n gywir), y cyfrif yswiriant yn llofnodi'r ail archeb a'r trafodiad cyfan ac yn ei anfon i'r blockchain.

Os na fydd pryniant yn digwydd, gall y defnyddiwr greu ExchangeTransaction yn unol â'r rheolau a ddisgrifir yn y sgript ac anfon y trafodiad i'r blockchain. Fel hyn gall y defnyddiwr ddychwelyd yr arian a wariwyd ar brynu tocynnau yswiriant.

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

Gellir gwneud tocyn yswiriant yn ased smart, er enghraifft, i wahardd ei drosglwyddo i drydydd partïon.

Gellir gweithredu'r cynllun hwn hefyd ar gyfer tocynnau cyllido torfol, sy'n cael eu dychwelyd i'r perchnogion os nad yw'r swm gofynnol wedi'i gasglu.

Trethi trafodion

Mae contractau clyfar hefyd yn berthnasol mewn achosion lle mae angen casglu treth ar bob trafodiad gyda sawl math o ased. Gellir gwneud hyn trwy ased newydd gyda gosod nawdd ar gyfer trafodion gydag asedau clyfar:

1. Rydym yn cyhoeddi FeeCoin, a fydd yn cael ei anfon at ddefnyddwyr am bris sefydlog: 0,01 WAVES = 0,001 FeeCoin.

2. Gosod nawdd ar gyfer FeeCoin a chyfradd gyfnewid: 0,001 WAVES = 0,001 FeeCoin.

3. Gosodwch y sgript ganlynol ar gyfer yr ased smart:

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
}

Nawr bob tro y bydd rhywun yn trosglwyddo N asedion craff, byddant yn rhoi FeeCoin i chi yn y swm o N/trethDivisor (y gellir ei brynu oddi wrthych am 10 * N / taxDivisor WAVES), a byddwch yn rhoi N/TONNAU Rhannwr treth i'r glöwr. O ganlyniad, eich elw (treth) fydd 9*N / trethRhannwr TONNAU.

Gallwch hefyd berfformio trethiant gan ddefnyddio sgript asedau clyfar a 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
}

Arian yn ôl a rhaglenni teyrngarwch

Mae arian yn ôl yn fath o raglen teyrngarwch lle mae'r prynwr yn adennill rhan o'r swm a wariwyd ar gynnyrch neu wasanaeth.

Wrth weithredu'r achos hwn gan ddefnyddio cyfrif smart, rhaid i ni wirio'r proflenni yn yr un modd ag y gwnaethom yn yr achos yswiriant. Er mwyn atal gwariant dwbl, rhaid i'r defnyddiwr anfon DataTransaction gyda (allwedd, gwerth) = (prynuTransactionId, cashbackTransactionId) cyn derbyn arian yn ôl.

Rhaid inni hefyd osod gwaharddiad ar allweddi presennol gan ddefnyddio DataTransaction. CashbackDivisor - uned wedi'i rhannu â'r gyfran arian yn ôl. Y rhai. os yw'r gyfran arian yn ôl yn 0.1, yna 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)
}

Cyfnewid atomig

Mae cyfnewid atomig yn caniatáu i ddefnyddwyr gyfnewid asedau heb gymorth cyfnewidfa. Gyda chyfnewid atomig, mae'n ofynnol i'r ddau gyfranogwr yn y trafodiad ei gadarnhau o fewn cyfnod penodol o amser.

Os na fydd o leiaf un o'r cyfranogwyr yn darparu cadarnhad cywir o'r trafodiad o fewn yr amser a neilltuwyd ar gyfer y trafodiad, caiff y trafodiad ei ganslo ac nid yw'r cyfnewid yn digwydd.

Yn ein hesiampl, byddwn yn defnyddio'r sgript cyfrif clyfar canlynol:

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
}

Yn yr erthygl nesaf byddwn yn edrych ar y defnydd o gyfrifon clyfar mewn offerynnau ariannol megis opsiynau, dyfodol a biliau.

Ffynhonnell: hab.com

Ychwanegu sylw