company_banner

Смарт-ассеты Waves: «черные» и «белые» списки, интервальный трейдинг

    image

    В двух предыдущих статьях мы рассказали о смарт-аккаунтах и о том, как они могут использоваться для проведения аукционов и создания программ лояльности, а также помогают обеспечить прозрачность финансовых инструментов.

    Сейчас мы рассмотрим смарт-ассеты и несколько кейсов их применения, включая замораживание активов и создание ограничений на транзакции по заданным адресам.


    Смарт-ассеты Waves позволяют пользователям накладывать скрипты на ассеты, следуя той же механике, что и в случае со смарт-аккаунтами. Каждая новая транзакция, созданная с использованием смарт-ассета, будет подтверждена сначала скриптом, и только потом блокчейном.

    Стоит отметить следующие отличия смарт-ассетов от смарт-аккаунтов:

    1. В коде смарт-ассета нельзя осуществить проверку пруфов (о них мы говорили в первой статье).
    2. В коде смарт-аккаунта можно проверять ExchangeTransaction, только если ваш аккаунт является аккаунтом-матчером. В противном случае проверяется только ордер. В коде смарт-ассета проверить непосредственно ордер нельзя, можно проверять ExchangeTransaction, и из неё уже при необходимости извлекать ордер.
    3. У смарт-ассета, в отличие от смарт-аккаунта, нет стейта, но мы все же имеем доступ к стейтам аккаунтов из скрипта.

    Смарт-ассеты значительно упрощают написание контрактов, делая реализацию многих кейсов лаконичной и элегантной.

    Заморозка активов

    Чтобы заморозить активы до определенной высоты блока targetHeight, можно просто задать это значение в скрипте следующего смарт-ассета:

    let targetHeight = 1500000
    height >= targetHeight
     
    height - функция языка, возращающая текущую высоту.
    

    Условие конкретного матчера

    Чтобы установить в качестве желаемого конкретный матчер, вы можете задать его адрес в качестве отправителя в скрипте смарт-ассета следующего вида:

    match tx {
        case t : ExchangeTransaction =>
            t.sender == addressFromString("3PJaDyprvekvPXPuAtxrapacuDJopgJRaU3")
        case _ => true
    }
    

    «Белый список» получателей

    Чтобы разрешить отправку токенов только на определенные счета — создать «белый список» получателей — вы можете использовать смарт-ассет со следующей схемой, проверяющей вхождение в список:

    match tx {
      case t : TransferTransaction =>
        let trustedRecipient1 = addressFromString("3P6ms9EotRX8JwSrebeTXYVnzpsGCrKWLv4")
        let trustedRecipient2 = addressFromString("3PLZcCJyYQnfWfzhKXRA4rteCQC9J1ewf5K")
        let trustedRecipient3 = addressFromString("3PHrS6VNPRtUD8MHkfkmELavL8JnGtSq5sx")
        t.recipient == trustedRecipient1 || t.recipient == trustedRecipient2 || t.recipient == trustedRecipient3
      case _ => false
    }
    

    В целях безопасности и доказуемой завершимости языка список не содержит реализации итератора. Поэтому он задан в качестве набора конкретных элементов.

    «Черный список» получателей

    Точно так же, для запрета на отправку токенов на определенные счета, вы можете создать «черный список». При этом используется абсолютно такой же смарт-ассет, но с проверкой адреса на отсутствие в черном списке:

    match tx {
      case t : TransferTransaction =>
        let bannedRecipient1 = addressFromString("3P6ms9EotRX8JwSrebeTXYVnzpsGCrKWLv4")
        let bannedRecipient2 = addressFromString("3PLZcCJyYQnfWfzhKXRA4rteCQC9J1ewf5K")
        let bannedRecipient3 = addressFromString("3PHrS6VNPRtUD8MHkfkmELavL8JnGtSq5sx")
        t.recipient != bannedRecipient1 && t.recipient != bannedRecipient2 && t.recipient != bannedRecipient3
      case _ => false
    }
    

    Отправка с разрешения эмитента

    При помощи смарт-ассета можно также установить опцию отправки смарт-ассета только с разрешения эмитента (commitment/debt label). Эмитент выражает свое согласие, разместив ID транзакции в стейте своего аккаунта:

    match tx {
      case t : TransferTransaction =>
        let issuer = extract(addressFromString("3P6ms9EotRX8JwSrebeTXYVnzpsGCrKWLv4"))
        #убеждаемся, что в стейте эмитента содержится ID текущей транзакции
        isDefined(getInteger(issuer, toBase58String(t.id)))
      case _ => false
    }
    

    Обмен только на определенные монеты

    Cмарт-ассет допускает разрешение обменивать его только на определенные монеты. Например, чтобы разрешить обмен только на биткойны, можно использовать следующий код:

    let BTCId = base58'8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS'
    match tx {
      case t : ExchangeTransaction =>
        t.sellOrder.assetPair.priceAsset == BTCId ||
         t.sellOrder.assetPair.amountAsset == BTCId
      case _ => true
    }
    

    Торговля по цене от оракула

    В скрипте смарт-ассета можно задать разрешение на торговлю только по цене, зафиксированной в стейте надежного оракула. Вот пример такого скрипта:

    let oracle = Address(base58'3PLNmokt22NrSiNvCLvwMUP84LCMJqbXwAD')
    let assetId = toBase58String(base58'oWgJN6YGZFtZrV8BWQ1PGktZikgg7jzGmtm16Ktyvjd')
     
    match tx {
      #запрещаем передачу ассета
      case t: TransferTransaction | MassTransferTransaction => false
      case e: ExchangeTransaction =>
        #убеждаемся, что торговля происходит по цене, заданной в стейте оракла для этого ассета
        let correctPrice = e.price == extract(getInteger(oracle, assetId))
        #убеждаемся, что торговля происходит в обмен на WAVES
        let correctPriceAsset = !isDefined(e.sellOrder.assetPair.priceAsset) 
    correctPrice && correctPriceAsset
      case _ => true
    }
    

    Здесь мы сталкиваемся с неочевидным моментом при проверке ID ассета, с которым осуществляется торговля. Дело в том, что, если ID ассета не определен, значит, речь идет о WAVES. В скрипте мы убеждаемся, что торговля осуществляется в паре с WAVES, именно таким образом.

    Фиксированное увеличение цены

    Можно установить фиксированную цену смарт-ассета, которая будет пошагово увеличиваться в заданной пропорции. Вот пример скрипта ассета, цена которого будет увеличивается на 5% каждые 1000 блоков:

    let startPrice = 10
    let startHeight = 1000
    let interval = 1000
    #на сколько процентов цена увеличивается за один шаг
    let raise = 5
     
    match tx {
      case t: TransferTransaction | MassTransferTransaction => false
      case e: ExchangeTransaction =>
        e.price == startPrice + ((height - startHeight) / interval) * (100 + raise) / 100
        && !isDefined(e.sellOrder.assetPair.priceAsset)
      case _ => true
    }
    

    Интервальный трейдинг

    Также, благодаря скрипту, торговлю смарт-ассетом можно ограничить заранее определенными интервалами. Вот пример такого скрипта:

    let startHeight = 10000
    let interval = 44000
    let limit = 1500
     
    match tx {
      case t: TransferTransaction | MassTransferTransaction | ExchangeTransaction =>
        (height - startHeight) % interval < limit
      case _ => true
    }
    

    В скрипте мы убеждаемся, что с начала торговли startHeight прошло не более, чем limit интервалов. Длина интервала равна количеству блоков, заданному в поле interval.
    Waves
    59,00
    Компания
    Поделиться публикацией

    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое