Каржылык инструменттерде Waves акылдуу эсептерин жана акылдуу активдерди колдонуу

Каржылык инструменттерде Waves акылдуу эсептерин жана акылдуу активдерди колдонуу

Мурунку макала Биз бизнесте смарт эсептерди колдонуунун бир нече учурларын, анын ичинде аукциондорду жана лоялдуулук программаларын карадык.
Бүгүн биз акылдуу эсептер жана акылдуу активдер опциондор, фьючерстер жана векселдер сыяктуу финансылык инструменттердин ачык-айкындуулугун жана ишенимдүүлүгүн кантип жакшыртаары жөнүндө сүйлөшөбүз.

Вариант

Опцион – бул сатып алуучуга активди белгилүү бир баада же белгилүү бир мөөнөткө чейин сатып алуу укугун берген, бирок аны буга милдеттендирбеген алмашуу келишими.

Опцияны ишке ашыруу төмөнкүдөй болушу мүмкүн:

Биз инструмент катары опциондор үчүн акылдуу активди жана алмашуу жана варианттарды чыгарган катышуучу үчүн акылдуу эсепти колдонобуз. Алмашуу катышуучусу белгилүү бир активдин белгилүү бир суммасын expirationStart жана expirationEnd блок бийиктиктеринин ортосунда sellPrice баасында сатаарына убада берет).

Акылдуу активдин кодунда биз жөн гана анын көрсөтүлгөн бийиктиктердин ортосунда гана соодаланганын текшеребиз жана башка эч нерсени текшербейбиз, эрежелердин сакталышы үчүн бардык жоопкерчиликти алмашуу катышуучусунун кодуна калтырабыз.

Акылдуу актив коду:

let expirationStart = 100000
let expirationEnd = 101440

match tx {
   case some : ExchangeTransaction | TransferTransaction =>
       height > expirationStart && height <= expirationEnd
   case _ => false
}

Биз иш-аракеттер төмөнкүчө ишке ашат деп ойлойбуз: биржа катышуучусу кандайдыр бир активди сатып алуу үчүн опциондорду сатат, ал эми башка катышуучулар бул опцияларды жөнөтө алышат же соодалаша алышат. Сатып алуу укугун ишке ашыруу үчүн потенциалдуу сатып алуучу сатуучунун, башкача айтканда, алмашуунун катышуучусунун эсебине каалаган сандагы варианттарды которуусу керек. Андан кийин, ал алмашуунун катышуучусунун мамлекеттик эсебине которуу аяктаганы жөнүндө маалыматты жазат, ошондон кийин гана ExchangeTransaction белгиленген сатып алуу-сатуу шарттарына ылайык иштей алат.

Акылдуу эсептин кодунда биз акыркы сатып алуу-сатуу актысы үчүн ал аркылуу өткөн ар кандай ExchangeTransaction көрсөтүлгөн шарттарга жооп берерин, ал эми катышуучу биржа катышуучунун эсебине жөнөткөн бирдиктердин так санын сатып аларын текшеришибиз керек. Потенциалдуу сатып алуучу которуу жөнүндө туура DataTransaction жөнөтүшү керек, ошентип алмашуу катышуучусу эки эсе чыгымдан качышы үчүн. Бул DataTransaction-да сатып алуучу өз дарегине барабар ачкычка ылайык, алмашуу катышуучунун эсебине которулган варианттардын санына барабар маанини коет, башкача айтканда, ал сатып ала турган актив бирдиктеринин санына барабар.

Акылдуу эсеп коду:

#владелец аккаунта дает обязательство продать определенное количество юнитов ассета
#по цене sellPrice между высотами блоков expirationStart и expirationEnd

let expirationStart = 100000
let expirationEnd = 101440
let sellPrice = 10000
let amountAsset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
let priceAsset = base58'9jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
#ID ассета-опциона
let optionsAsset = base58'7jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
#извлекаем из транзакции адрес отправителя
let this = tx.sender
match tx {
   case dataTx : DataTransaction =>
       #извлекаем количество юнитов из дата-транзакции по ключу (ID пользователя)
       let units = extract(getInteger(dataTx.data, dataTx.data[0].key))

       #извлекаем трансфер-транзакцию опционов из пруфа
       let e = transactionById(dataTx.proofs[2]) #
       match e {
           case transferTx : TransferTransaction =>
               #убеждаемся, что трансфер был на текущий адрес
               (transferTx.recipient == this) &&
               #убеждаемся, что отправитель транзакции написал в качестве ключа свой ID
               dataTx.data[0].key == toBase58String(transferTx.sender.bytes) &&
               sigVerify(dataTx.bodyBytes, dataTx.proofs[0], transferTx.senderPublicKey) &&
               #убеждаемся, что указанное количество юнитов соответствует посланному количеству опционов
               (units == transferTx.amount) &&
               #убеждаемся, что был переведен именно ассет-опцион
               (transferTx.assetId == optionsAsset)              
           case _ => false
       } &&
       size(dataTx.data) == 1 && !isDefined(getInteger(this, dataTx.data[0].key))
       && height > expirationStart && height <= expirationEnd
   case exchangeTx : ExchangeTransaction =>
       #убеждаемся, что итоговый обмен происходит по указанным заранее правилам
       let correctAssetPair = exchangeTx.sellOrder.assetPair.amountAsset == amountAsset &&
                                   exchangeTx.sellOrder.assetPair.priceAsset == priceAsset
       let correctPrice = exchangeTx.sellOrder.price == sellPrice
       #извлекаем дата-транзакцию из пруфа      
       let d = transactionById(exchangeTx.proofs[2])
       match d{
           case dataTx : DataTransaction =>
               let buyOrderSender = dataTx.data[0].key
               toBase58String(exchangeTx.buyOrder.sender.bytes) == buyOrderSender &&
               exchangeTx.amount == extract(getInteger(dataTx.data, buyOrderSender))
           case _ => false
       } &&
       exchangeTx.sellOrder.sender == this &&
       correctAssetPair && correctPrice &&
       height > expirationStart && height <= expirationEnd
   case _ => false
}

Акылдуу эсептер боюнча фьючерс

Опциондон айырмаланып, фьючерс (фьючерстик келишим) бул укук эмес, сатып алуучунун келечекте белгилүү бир учурда келишимде белгиленген баада активди сатып алуу милдети.

Жалпысынан келечекти жазуу вариантты жазууга окшош. Бул жерде акылдуу актив келечектин ролун аткарат.

Ошондой эле сатып алуучу да, сатуучу да сатып алуу буйругуна кол койгонуна ынанышыңыз керек. Келечек кандай болгон күндө да аткарылышы керек болгон милдет. Бул сатуучу же катышуучу өз милдеттеринен баш тартса, тармактын каалаган катышуучусу транзакцияны жөнөтө алат, ошону менен келечекти ишке ашыра алат дегенди билдирет.

Акылдуу актив скрипти фьючерстик активдин бардык TransferTransactions жана ExchangeTransactions көзөмөлдөйт, эгерде сатып алуучу катышуучу биржа катышуучусунан фьючерстик активди келечекте сатып алуу үчүн буйрутманы түзсө гана аларды бекитет.

Бул буйрук жарактуу болушу керек жана фьючерс берилген шарттарды канааттандырышы керек. Буйрутманы текшерүү үчүн анын бардык талааларын сатып алуучунун эсебинин абалына жана кол коюлган буйрутма байт көрсөтүүсүнө киргизип, андан кийин тышкы валидацияны аткара аласыз.

Учурда RIDE транзакция байттарын талдоо үчүн жергиликтүү функцияны камтыбайт, бирок аны ишке ашыруу үчүн зарыл болгон бардык куралдарды камтыйт. Ошондуктан, иштеп чыгуучулар бул функцияны өздөрү ишке ашырууга аракет кылышы мүмкүн.

Көп кол тамга эсеби / Эскроу

Көп кол тамгалуу эсеп бир нече колдонуучуларга активдерди биргелешип башкарууга мүмкүндүк берет (мисалы, активдер менен транзакциялар төрт колдонуучунун үчөөсүнүн кол тамгасы болгондо гана мүмкүн болушу мүмкүн). RIDE тилинде көп кол тамга эсептерди түзүү үчүн, биз транзакция далилдерин колдоно алабыз.

Көп кол тамгалуу эсепти эскроу эсеби катары да колдонсо болот, анда каражаттар келишимдин тараптары өз милдеттенмелерин аткарганга чейин сакталат.

let alicePubKey  = base58'5AzfA9UfpWVYiwFwvdr77k6LWupSTGLb14b24oVdEpMM'
let bobPubKey    = base58'2KwU4vzdgPmKyf7q354H9kSyX9NZjNiq4qbnH2wi2VDF'
let cooperPubKey = base58'GbrUeGaBfmyFJjSQb9Z8uTCej5GzjXfRDVGJGrmgt5cD'
#выясняем, кто предоставил корректные подписи
let aliceSigned  = if(sigVerify(tx.bodyBytes, tx.proofs[0], alicePubKey)) then 1 else 0
let bobSigned    = if(sigVerify(tx.bodyBytes, tx.proofs[1], bobPubKey)) then 1 else 0
let cooperSigned = if(sigVerify(tx.bodyBytes, tx.proofs[2], cooperPubKey)) then 1 else 0
#суммируем все корректные подписи и проверяем их количество
aliceSigned + bobSigned + cooperSigned >= 2

Токендердин реестри (TCR)

Көптөгөн блокчейн платформаларында уулуу активдер көйгөйү бар. Мисалы, комиссия төлөгөн ар бир дарек Waves боюнча актив түзө алат.

Колдонуучуларды жана блокчейндин өзүн уулуу активдерден коргоо маселеси токен ээлери тарабынан түзүлгөн токендерди куратордук реестр (TCR) аркылуу чечилет.

Тизмеге кошула турган белгилүү бир белги үчүн добуш берүү үчүн, ээси чыгарылган токендердин жалпы санынан өзүнүн үлүшүнө барабар тендерди коёт. Токен ээлеринин көпчүлүгү добуш берсе, реестрге киргизилет.

Биздин мисалда, биз колдонуучуга эсептин учурдагы мааниси = 0 болгондо гана мамлекеттик ачкыч = asset_name аркылуу карап чыгуу үчүн тизмеге белги кошууга уруксат беребиз ("чакырык" мезгилинде).

Ошондой эле, колдонуучунун капчыгында бул белгинин нөл эмес балансы болушу керек. Андан кийин добуш берүү мезгили келет, анын жүрүшүндө колдонуучу капчыгындагы ар бир активге добуш бере алат, бирок бир гана жолу, 1ден 10го чейин баа бере алат. Колдонуучунун добуштары user_address+assetID формасынын ачкычтары менен көрсөтүлөт.

let asset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
let addingStartHeight = 1000
let votingStartHeight = 2000
let votingEndHeight = 3000

#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)

#извлекаем адрес из пруфа транзакции
let address = addressFromPublicKey(tx.proofs[1])
match tx {
   case t: DataTransaction =>
       if(height > addingStartHeight)
       then(
           if(height < votingStartHeight)
           then(
               #adding
               #выясняем, есть ли этот ассет у этого адреса
               let hasTokens = assetBalance(address, asset) > 0
               size(t.data) == 1
                     #убеждаемся, что этот ассет еще не был добавлен
                     && !isDefined(getInteger(this, toBase58String(asset)))
                     #убеждаемся, что по ключу-ассету добавляется значение равное 0
                     && extract(getInteger(t.data, toBase58String(asset))) == 0
                     && hasTokens
           )
           else(
               if(height < votingEndHeight)
               then
               (
                   #voting
                   #узнаем текущее количество голосов за данный ассет и задаваемое количество
                   let currentAmount = extract(getInteger(this, toBase58String(asset)))
                   let newAmount = extract(getInteger(t.data, toBase58String(asset)))
                   let betString = toBase58String(address.bytes) + toBase58String(asset)

                   #убеждаемся, что этот адрес еще не голосовал за этот ассет
                   let noBetBefore = !isDefined(getInteger(this, betString))
                   let isBetCorrect = extract(getInteger(t.data, betString)) > 0
                       && extract(getInteger(t.data, betString)) <= 10
                  
                   #убеждаемся, что у голосующего есть необходимые токены
                   let hasTokens = assetBalance(address, asset) > 0
                   #проверяем корректность значений транзакции
                   size(t.data) == 2 && isDefined(getInteger(this, toBase58String(asset)))
                       && newAmount == currentAmount + 1
                       && noBetBefore && isBetCorrect && hasTokens
               )
               else false
           ) && sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1])
       )
       else false
   case _ => false
}

Абоненттик толом

Бул мисалда биз өнүм же кызмат үчүн белгиленген мөөнөттөрдө үзгүлтүксүз төлөмдөрдү жүргүзүү үчүн акылдуу эсептерди колдонууну карайбыз - “абоненттик төлөмдөр”.
Эгерде колдонуучу смарт-аккаунтту (транзакциянын далилдери аркылуу) которулган акчанын керектүү суммасы менен TransferTransaction ID менен камсыз кылса, ал эсептин абалына {ачкыч: дарек, маани:) деп жаза алат. чыныгы}.

Бул колдонуучу өнүмгө же кызматка жазылуусун тастыктайт дегенди билдирет. Жазылуу мөөнөтү аяктаганда, ар бир тармак колдонуучусу мамлекеттеги тиешелүү ачкычтын карама-каршы маанисин орното алат жалган.

let subscriptionPeriod = 44000
let signature = tx.proofs[0]
let pk = tx.proofs[1]
let requiredAmount = 100000

#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)
match tx {
   case d: DataTransaction =>
     #извлекаем дату последнего платежа
     let lastPaymentHeight = extract(getInteger(this, d.data[0].key + "_lastPayment"))
     size(d.data) == 1 && d.data[0].value == "false" && lastPaymentHeight + subscriptionPeriod < height
     ||
     (
       let address = d.data[0].key

       #извлекаем трансфер-транзакцию по ID, указанному в пруфах
       let ttx = transactionById(d.proofs[0])
       
       size(d.data) == 2
           && d.data[0].value == "true"
           && d.data[1].key == address + "_lastPayment"
           && match ttx {
             case purchase : TransferTransaction =>
               d.data[1].value == transactionHeightById(purchase.id)
               && toBase58String(purchase.sender.bytes) == address
               && purchase.amount == requiredAmount
               && purchase.recipient == this
               #убеждаемся, что ассет waves
               && !isDefined(purchase.assetId)
         case _ => false
       }
     )
   case _ => false
}

добуш берүү

Smart эсептерди блокчейнде добуш берүүнү ишке ашыруу үчүн колдонсо болот. Мисал катары элчи программасынын алкагында мыкты элчинин баяндамасына добуш берүү болот. Эсептин абалы белгилүү бир вариант үчүн добуштарды жазуу үчүн платформа катары колдонулат.

Бул мисалда, добуш берүүгө атайын "добуш берүү" белгилерин сатып алгандар гана уруксат берилет. Катышуучу жуп (ачкыч, маани) = (purchaseTransactionId, buyTransactionId) менен алдын ала DataTransaction жөнөтөт. Бул ачкыч үчүн башка маани коюуга тыюу салынат. Дарегиңизди жана добуш берүү опцияңызды колдонуп, сиз DataEntry бир гана жолу орното аласыз. Добуш берүү көрсөтүлгөн мөөнөттө гана мүмкүн.

let asset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
let address = addressFromPublicKey(tx.proofs[1])
let votingStartHeight = 2000
let votingEndHeight = 3000

#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)
 match tx {
   case t: DataTransaction =>
     (height > votingStartHeight && height < votingEndHeight) &&
     #убеждаемся, что у транзакции правильная подпись
     sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) &&

     #проверяем, что пользователь отдает свой голос напротив своего адреса
     if (t.data[0].key == toBase58String(address.bytes))
     then (
       #извлекаем транзакцию перевод голосовательного токена из пруфов
       let purchaseTx = transactionById(t.proofs[7])
       
       match purchaseTx {
         case purchase : TransferTransaction =>
           let correctSender = purchase.sender == t.sender
           let correctAsset = purchase.assetId == asset
           let correctPrice = purchase.amount == 1
           let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == t.id
           correctSender && correctAsset && correctPrice && correctProof
         case _ => false
       }
     )
     else
         size(t.data) == 1 && !isDefined(getBinary(this, t.data[0].key))
   case _ => false
}

вексель

Вексель – бир тарап экинчи тарапка белгиленген сумманы талап боюнча же алдын ала белгиленген мөөнөттө төлөөнү талап кылган жазуу жүзүндөгү милдеттенме.

Биздин мисалда биз акылдуу эсепти колдонобуз, анын мөөнөтү векселдин төлөм датасына туура келет.

let expiration = 100000
let amount = 10
let asset =  base58'9jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
  
let Bob = Address(base58'3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8')
let Alice = Address(base58'3PNX6XwMeEXaaP1rf5MCk8weYeF7z2vJZBg')
  
match tx {
    case t: TransferTransaction =>
        (t.assetId == asset)&&      
        (t.amount == amount)&&       
        (t.sender == Bob)&&
        (t.recipient == Alice)&&
        (sigVerify(t.bodyBytes, t.proofs[0], t.senderPublicKey))&&
        (height >= expiration)
    case _ => false
}

депозиттик

Депозит – бул белгилүү бир шарттарда (мөөнөт, пайыз) акча каражаттарын банкка жайгаштыруу.
Биздин мисалда банктын функциясын смарт эсеп аткарат. Депозиттик мөөнөткө туура келген белгилүү бир сандагы блоктордон кийин колдонуучу өз акчасын пайыздар менен кайтара алат. Скрипт блоктун бийиктигин (finalHeight) көрсөтөт, ага жеткенден кийин колдонуучу эсептен акча ала алат.

heightUnit - убакыттын бир бирдигиндеги блоктордун саны (мисалы, ай, жыл ж.б.). Алгач биз жуп (ачкыч, маани) = (initialTransferTransaction, futureDataTransaction) менен жазууну текшеребиз. Андан кийин колдонуучу депозиттин суммасы жана депозиттин мөөнөтү үчүн чегерилген пайыздар жөнүндө туура маалымат менен TransferTransaction тапшырышы керек. Бул маалымат учурдагы TransferTransaction далилинде камтылган түпнуска TransferTransaction менен текшерилет. depositDivisor – депозиттин үлүшүнүн тескери саны (эгер депозит 10% менен кабыл алынса, депозиттин үлүшү 0,1, ал эми depositDevisor = 1/0,1 = 10).

let this = extract(tx.sender)
let depositDivisor = 10
let heightUnit = 1000
let finalHeight = 100000
 match tx {
   case e : TransferTransaction =>
     #извлекаем высоту транзакции по ID транзакции в седьмом пруфе  
     let depositHeight = extract(transactionHeightById(e.proofs[7]))

     #извлекаем транзакцию депозита
     let purchaseTx = transactionById(e.proofs[7])    
     match purchaseTx {
       case deposit : TransferTransaction =>
         let correctSender = deposit.sender == e.sender
         #убеждаемся, что пользователь переводит себе корректную сумму депозита + проценты
         let correctAmount = deposit.amount + deposit.amount / depositDivisor * (height - depositHeight) / heightUnit == e.amount
         let correctProof = extract(getBinary(this, toBase58String(deposit.id))) == e.id
         correctSender && correctProof && correctAmount
       case _ => false
     }
     && finalHeight <= height 
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Бул сериядагы үчүнчү жана акыркы макалада биз акылдуу активдердин көбүрөөк колдонулушун, анын ичинде белгилүү бир даректер үчүн транзакцияларды тоңдурууну жана чектөөнү карайбыз.

Source: www.habr.com

DDoS коргоосу, VPS VDS серверлери бар сайттар үчүн ишенимдүү хостинг сатып алыңыз 🔥 DDoS коргоосу, VPS VDS серверлери бар ишенимдүү веб-сайт хостингин сатып алыңыз | ProHoster