Waves Smart Assets: Black and White Lists, Interval Trading

    image

    In two previous articles, we talked about smart accounts and how they can be used to conduct auctions and create loyalty programs , and also help ensure the transparency of financial instruments .

    Now we will consider smart assets and several cases of their application, including freezing assets and creating restrictions on transactions at specified addresses.


    Waves Smart Assets allow users to overlay scripts on assets, following the same mechanics as with smart accounts. Each new transaction created using the smart asset will be confirmed first by the script, and only then by the blockchain.

    It is worth noting the following differences between smart assets and smart accounts:

    1. It is not possible to verify proofs in the smart asset code (we talked about them in the first article ).
    2. In the smart account code, you can check ExchangeTransaction only if your account is a match account. Otherwise, only the order is checked. You cannot check the order directly in the smart asset code, you can check the ExchangeTransaction, and if necessary, extract the order from it.
    3. A smart asset, unlike a smart account, does not have a state, but we still have access to the account states from the script.

    Smart assets greatly simplify the writing of contracts, making the implementation of many cases concise and elegant.

    Freezing assets

    To freeze assets to a certain height of the targetHeight block , you can simply set this value in the script of the following smart asset:

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

    Condition of a specific matchmaker

    To set a specific matchup as desired, you can specify its address as a sender in a smart asset script of the following form:

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

    “White list” of recipients

    To allow sending tokens only to certain accounts - to create a “white list” of recipients - you can use a smart asset with the following scheme, which checks entry into the list:

    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
    }
    

    For security and provable language consistency, the list does not contain an iterator implementation. Therefore, it is defined as a set of specific elements.

    Blacklist of recipients

    In the same way, to prohibit sending tokens to certain accounts, you can create a blacklist. In this case, the exact same smart asset is used, but with the address checked for absence on the black list:

    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
    }
    

    Sending with permission of the issuer

    Using a smart asset, you can also set the option to send a smart asset only with permission of the issuer (commitment / debt label ). The issuer expresses its consent by posting the transaction ID in the style of his account:

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

    Exchange only for certain coins

    Smart Asset allows permission to exchange it only for certain coins. For example, to allow exchange only for bitcoins, you can use the following code:

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

    Trading at the price of the oracle

    In the smart asset script, you can set the permission to trade only at the price fixed in the reliable oracle's story. Here is an example of such a script:

    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
    }
    

    Here we are faced with a non-obvious point when checking the ID of the asset with which the trade is carried out. The fact is that if the asset ID is not defined, then we are talking about WAVES. In the script, we make sure that trading is paired with WAVES, in this way.

    Fixed price increase

    You can set a fixed price for a smart asset, which will incrementally increase in a predetermined proportion. Here is an example asset script, the price of which will increase by 5% every 1000 blocks:

    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
    }
    

    Interval trading

    Also, thanks to the script, the trading of smart assets can be limited to predetermined intervals. Here is an example of such a script:

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

    In the script, we make sure that no more than limit intervals have passed since the start of trading startHeight . The interval length is equal to the number of blocks specified in the interval field .

    Also popular now: