Waves խելացի հաշիվների կիրառությունները՝ աճուրդներից մինչև բոնուսային ծրագրեր

Waves խելացի հաշիվների կիրառությունները՝ աճուրդներից մինչև բոնուսային ծրագրեր

Բլոկչեյնը հաճախ կապված է միայն կրիպտոարժույթների հետ, սակայն DLT տեխնոլոգիայի կիրառման ոլորտները շատ ավելի լայն են։ Բլոկչեյնի կիրառման ամենահեռանկարային ոլորտներից մեկը խելացի պայմանագիրն է, որը կատարվում է ավտոմատ կերպով և չի պահանջում վստահություն դրա մեջ մտնող կողմերի միջև:

RIDE – խելացի պայմանագրերի լեզու

Waves-ը մշակել է խելացի պայմանագրերի հատուկ լեզու՝ RIDE: Դրա ամբողջական փաստաթղթերը գտնվում են այստեղ. Եվ այստեղ - հոդված այս թեմայով վրա Habr.

RIDE պայմանագիրը պրեդիկատ է և որպես արդյունք վերադարձնում է «ճշմարիտ» կամ «կեղծ»: Համապատասխանաբար, գործարքը կա՛մ գրանցվում է բլոկչեյնում, կա՛մ մերժվում է: Խելացի պայմանագիրը լիովին երաշխավորում է նշված պայմանների կատարումը: RIDE-ում պայմանագրով գործարքներ ստեղծելը ներկայումս հնարավոր չէ:

Այսօր գոյություն ունի Waves խելացի պայմանագրերի երկու տեսակ՝ խելացի հաշիվներ և խելացի ակտիվներ: Խելացի հաշիվը սովորական օգտվողի հաշիվ է, սակայն դրա համար սահմանված է սցենար, որը վերահսկում է բոլոր գործարքները: Խելացի հաշվի սցենարը կարող է այսպիսի տեսք ունենալ, օրինակ.

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

tx-ը մշակվող գործարք է, որը մենք թույլ ենք տալիս օգտագործել օրինաչափությունների համապատասխանության մեխանիզմը միայն այն դեպքում, եթե դա փոխանցման գործարք չէ: RIDE-ում օրինաչափությունների համընկնումն օգտագործվում է գործարքի տեսակը ստուգելու համար: Բոլոր գոյություն ունեցող հաշիվները կարող են մշակվել խելացի հաշվի սցենարով գործարքների տեսակները.

Սկրիպտը կարող է նաև փոփոխականներ հայտարարել, օգտագործել «եթե-ապա-ուրիշ» կառուցվածքները և այլ մեթոդներ՝ պայմաններն ամբողջությամբ ստուգելու համար: Ապահովելու համար, որ պայմանագրերն ունենան ապացուցելի ամբողջականություն և բարդություն (արժեք), որը հեշտ է կանխատեսել մինչև պայմանագրի կատարումը սկսելը, RIDE-ը չի պարունակում հանգույցներ կամ թռիչքային հայտարարություններ:

Waves հաշիվների այլ առանձնահատկությունները ներառում են «վիճակի» առկայությունը, այսինքն՝ հաշվի վիճակը: Դուք կարող եք անսահման թվով զույգեր (բանալին, արժեք) գրել հաշվի վիճակին՝ օգտագործելով տվյալների գործարքները (DataTransaction): Այնուհետև այս տեղեկատվությունը կարող է մշակվել ինչպես REST API-ի, այնպես էլ ուղղակիորեն խելացի պայմանագրում:

Յուրաքանչյուր գործարք կարող է պարունակել մի շարք ապացույցներ, որոնցում կարող են մուտքագրվել մասնակցի ստորագրությունը, պահանջվող գործարքի ID-ն և այլն:

Աշխատանք RIDE-ի միջոցով IDE թույլ է տալիս տեսնել պայմանագրի կազմված տեսքը (եթե այն կազմված է), ստեղծել նոր հաշիվներ և սահմանել դրա համար սկրիպտներ, ինչպես նաև ուղարկել գործարքներ հրամանի տողով։

Ամբողջ ցիկլի համար, ներառյալ հաշիվ ստեղծելը, դրա վրա խելացի պայմանագիր տեղադրելը և գործարքներ ուղարկելը, կարող եք նաև օգտագործել գրադարան REST API-ի հետ փոխազդելու համար (օրինակ՝ C#, C, Java, JavaScript, Python, Rust, Elixir) . IDE-ի հետ աշխատելու համար պարզապես սեղմեք ՆՈՐ կոճակը:

Խելացի պայմանագրերի օգտագործման հնարավորությունները լայն են՝ սկսած գործարքների արգելումից մինչև որոշակի հասցեներ («սև ցուցակ») մինչև բարդ dApps:

Հիմա եկեք դիտարկենք բիզնեսում խելացի պայմանագրերի կիրառման կոնկրետ օրինակներ՝ աճուրդներ, ապահովագրություն և հավատարմության ծրագրեր ստեղծելիս:

Աճուրդներ

Հաջող աճուրդի պայմաններից մեկը թափանցիկությունն է. մասնակիցները պետք է վստահ լինեն, որ հնարավոր չէ շահարկել հայտերը: Դրան կարելի է հասնել բլոկչեյնի շնորհիվ, որտեղ բոլոր խաղադրույքների և դրանց կատարման ժամանակի վերաբերյալ անփոփոխ տվյալները հասանելի կլինեն բոլոր մասնակիցներին։

Waves բլոկչեյնում հայտերը կարելի է գրանցել աճուրդի հաշվի վիճակում DataTransaction-ի միջոցով:

Դուք կարող եք նաև սահմանել աճուրդի մեկնարկի և ավարտի ժամը՝ օգտագործելով բլոկի համարները. Waves բլոկչեյնում բլոկների առաջացման հաճախականությունը մոտավորապես հավասար է. 60 վայրկյան.

1. Անգլերեն աճող գնի աճուրդ

Անգլերեն աճուրդի վայրի մասնակիցները հայտ են ներկայացնում միմյանց հետ մրցակցության մեջ: Յուրաքանչյուր նոր խաղադրույք պետք է գերազանցի նախորդը: Աճուրդն ավարտվում է, երբ այլևս հայտատուներ չկան, որոնք կարող են գերազանցել վերջին հայտը: Այս դեպքում ամենաբարձր գնորդը պետք է տրամադրի նշված գումարը:

Կա նաև աճուրդի տարբերակ, երբ վաճառողը նվազագույն գին է սահմանում լոտի համար, իսկ վերջնական գինը պետք է գերազանցի այն։ Հակառակ դեպքում լոտը մնում է չվաճառված։

Այս օրինակում մենք աշխատում ենք աճուրդի համար հատուկ ստեղծված հաշվի հետ: Աճուրդի տեւողությունը 3000 բլոկ է, իսկ լոտի մեկնարկային գինը՝ 0,001 ԱԼԻՔ: Մասնակիցը կարող է հայտ ներկայացնել՝ ուղարկելով DataTransaction բանալի «գինը» և իր հայտի արժեքը:

Նոր հայտի գինը պետք է ավելի բարձր լինի այս բանալիի ներկայիս գնից, և մասնակիցը պետք է իր հաշվում ունենա առնվազն [new_bid + միջնորդավճար] նշաններ: Հայտատուի հասցեն պետք է գրանցվի DataTransaction-ի «ուղարկող» դաշտում, իսկ ընթացիկ հայտի բլոկի բարձրությունը պետք է լինի աճուրդի ժամանակահատվածում:

Եթե ​​աճուրդի ավարտին մասնակիցը սահմանել է ամենաբարձր գինը, նա կարող է ուղարկել ExchangeTransaction՝ վճարելու համապատասխան լոտի համար նշված գնով և արժութային զույգով:

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. Նվազող գների հոլանդական աճուրդ

Հոլանդական աճուրդում ի սկզբանե շատ բան առաջարկվում է ավելի բարձր գնով, քան գնորդը պատրաստ է վճարել: Գինը քայլ առ քայլ նվազում է, քանի դեռ մասնակիցներից մեկը չի համաձայնում գնել լոտը ընթացիկ գնով:

Այս օրինակում մենք օգտագործում ենք նույն հաստատունները, ինչ նախորդում, ինչպես նաև գնի քայլը, երբ դելտան նվազում է: Հաշվի սցենարը ստուգում է, թե արդյոք մասնակիցն իրոք առաջինն է խաղադրույք կատարել: Հակառակ դեպքում DataTransaction-ը չի ընդունվում բլոկչեյնի կողմից:

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. «Ամբողջ վճարովի» աճուրդ

«All-pay»-ն աճուրդ է, որտեղ բոլոր մասնակիցները վճարում են հայտը՝ անկախ նրանից, թե ով է շահում լոտը: Յուրաքանչյուր նոր մասնակից վճարում է հայտ, իսկ լոտը շահում է այն մասնակիցը, ով առավելագույն առաջարկ է անում:

Մեր օրինակում աճուրդի յուրաքանչյուր մասնակից DataTransaction-ի միջոցով հայտ է ներկայացնում (բանալին, արժեք)* = («հաղթող», հասցե), («գին», գին): Նման DataTransaction-ը հաստատվում է միայն այն դեպքում, եթե այս մասնակիցն արդեն ունի TransferTransaction իր ստորագրությամբ, և նրա հայտը բարձր է բոլոր նախորդներից: Աճուրդը շարունակվում է մինչև վերջի բարձրությունը հասնելը:

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

Ապահովագրություն / Crowdfunding

Եկեք դիտարկենք մի իրավիճակ, երբ դուք պետք է ապահովագրեք օգտվողների ակտիվները ֆինանսական կորուստներից: Օրինակ, օգտատերը երաշխիք է ուզում, որ եթե նշանն արժեզրկվի, նա կկարողանա հետ ստանալ այդ նշանների համար վճարված ամբողջ գումարը և պատրաստ է վճարել ողջամիտ ապահովագրություն:

Դա իրականացնելու համար պետք է թողարկվեն «ապահովագրական նշաններ»: Այնուհետև ապահովադիրի հաշվում տեղադրվում է սկրիպտ, որը թույլ է տալիս կատարել միայն այն փոխանակման գործարքները, որոնք համապատասխանում են որոշակի պայմաններին:

Կրկնակի ծախսերը կանխելու համար դուք պետք է օգտագործողից պահանջեք նախապես ուղարկել DataTransaction ապահովադիրի հաշվին (բանալին, արժեք) = (purchaseTransactionId, sellOrderId) և արգելել DataTransactions ուղարկել արդեն օգտագործված բանալիով:

Հետևաբար, օգտագործողի ապացույցները պետք է պարունակեն ապահովագրական նշանի գնման գործարքի ID-ն: Արժույթի զույգը պետք է լինի նույնը, ինչ գնման գործարքում: Արժեքը նույնպես պետք է հավասար լինի գնման պահին հաստատվածին` հանած ապահովագրության գինը:

Հասկանալի է, որ հետագայում ապահովագրական հաշիվը օգտատերից գնում է ապահովագրական ժետոններ ոչ ցածր գնով, քան նա գնել է դրանք. ապահովագրական հաշիվը ստեղծում է ExchangeTransaction, օգտագործողը ստորագրում է պատվերը (եթե գործարքը ճիշտ է կատարվում), ապահովագրական հաշիվը ստորագրում է երկրորդ պատվերը և ամբողջ գործարքը և այն ուղարկում բլոկչեյն:

Եթե ​​գնումներ տեղի չունենան, օգտատերը կարող է ստեղծել ExchangeTransaction՝ համաձայն սկրիպտում նկարագրված կանոնների և գործարքն ուղարկել բլոկչեյն: Այս կերպ օգտատերը կարող է վերադարձնել ապահովագրված ժետոնների գնման վրա ծախսված գումարը:

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

Ապահովագրական նշանը կարող է դառնալ խելացի ակտիվ, օրինակ՝ արգելելու դրա փոխանցումը երրորդ անձանց:

Այս սխեման կարող է կիրառվել նաև քրաուդֆանդինգի թոքենների համար, որոնք վերադարձվում են սեփականատերերին, եթե անհրաժեշտ գումարը չի հավաքվել։

Գործարքների հարկեր

Խելացի պայմանագրերը կիրառելի են նաև այն դեպքերում, երբ անհրաժեշտ է հարկ հավաքել մի քանի տեսակի ակտիվներով յուրաքանչյուր գործարքից։ Դա կարելի է անել տեղադրված նոր ակտիվի միջոցով հովանավորություն խելացի ակտիվների հետ գործարքների համար՝

1. Մենք թողարկում ենք FeeCoin, որը կուղարկվի օգտատերերին ֆիքսված գնով՝ 0,01 WAVES = 0,001 FeeCoin:

2. Սահմանեք հովանավորություն FeeCoin-ի և փոխարժեքի համար՝ 0,001 WAVES = 0,001 FeeCoin:

3. Սահմանեք հետևյալ սկրիպտը խելացի ակտիվի համար.

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
}

Այժմ ամեն անգամ, երբ ինչ-որ մեկը փոխանցում է N խելացի ակտիվներ, նրանք ձեզ կտան FeeCoin N/taxDivisor-ի չափով (որը կարելի է գնել ձեզնից 10 *N/taxDivisor WAVES-ով), և դուք կտաք հանքագործին N/taxDivisor WAVES: Արդյունքում ձեր շահույթը (հարկը) կլինի 9*N / taxDivisor WAVES:

Դուք կարող եք նաև հարկումը կատարել՝ օգտագործելով խելացի ակտիվների սցենարը և 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 և հավատարմության ծրագրեր

Cashback-ը հավատարմության ծրագրի մի տեսակ է, որի ժամանակ գնորդը հետ է ստանում ապրանքի կամ ծառայության վրա ծախսված գումարի մի մասը:

Սմարթ հաշիվ օգտագործելով այս դեպքն իրականացնելիս մենք պետք է ստուգենք ապացույցները այնպես, ինչպես դա արեցինք ապահովագրության դեպքում: Կրկնակի ծախսերը կանխելու համար օգտատերը պետք է ուղարկի DataTransaction (բանալին, արժեք) = (purchaseTransactionId, cashbackTransactionId) նախքան cashback ստանալը:

Մենք պետք է նաև արգելենք գոյություն ունեցող բանալիների վրա՝ օգտագործելով DataTransaction: cashbackDivisor - միավորը բաժանված է cashback մասնաբաժնի վրա: Նրանք. եթե cashback մասնաբաժինը 0.1 է, ապա 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)
}

Ատոմային փոխանակում

Ատոմային փոխանակումը թույլ է տալիս օգտվողներին փոխանակել ակտիվները առանց փոխանակման օգնության: Ատոմային սվոպի դեպքում գործարքի երկու մասնակիցները պարտավոր են հաստատել այն որոշակի ժամկետում:

Եթե ​​մասնակիցներից առնվազն մեկը գործարքի համար նախատեսված ժամկետում չի տրամադրում գործարքի ճիշտ հաստատում, գործարքը չեղյալ է հայտարարվում, և փոխանակում չի կատարվում:

Մեր օրինակում մենք կօգտագործենք հետևյալ խելացի հաշվի սցենարը.

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
}

Հաջորդ հոդվածում մենք կանդրադառնանք խելացի հաշիվների օգտագործմանը ֆինանսական գործիքներում, ինչպիսիք են օպցիոնները, ֆյուչերսները և օրինագծերը:

Source: www.habr.com

Добавить комментарий