🔗 On chain orders

The validation of orders on Perpetual3 platform is done on-chain with smart contracts

These smart contracts provide a secure environment for confirming and processing customer orders. The central component to this validation process is the use of digital signatures.

The customer supplies orders data signed by the merchant, the smart contract ensures that the submitted data by the customers is indeed authorized by the correct merchant.

The data validation is done by asserting

To implement this, the smart contract includes assertions that check the validity of the digital signature. Here's a simplified version of what's happening on Algorand Blockchain, written in PyTeal:

@ Subroutine(TealType.none)
def customer_new_orderV2():

    opup = OpUp(OpUpMode.OnCall)
    opup.maximize_budget(Int(10000))

    current_round = Global.round()

    merchant_pubkey = Txn.application_args[1]  # public key of merchant

    product_id = Txn.application_args[2] # product id is the hash of the product info
    product_id_price = Txn.application_args[3] # price is fiat price+currency
    product_id_signature = Txn.application_args[4]  # product id signature

    merchant_address = Txn.application_args[5]  # oracle data

    oracle_round = Txn.application_args[6]  # oracle round data
    oracle_data_signature = Txn.application_args[7]  # oracle data signature

    oraclePubKey = App.globalGetEx(
        Global.current_application_id(), Bytes("oraclePubKey"))

    oracle_data_verify = ScratchVar(TealType.bytes)
    product_id_data_verify = ScratchVar(TealType.bytes)
    payment_type_data_verify = ScratchVar(TealType.bytes)

    payment_type_signature = Txn.application_args[8]  # payment amount
    merchant_address_bytes = Txn.application_args[9]
    collection_type = Txn.application_args[10]
    collection_name = Txn.application_args[11]

    merchant_payment_txn = Gtxn[9]
    merchant_paymentType = merchant_payment_txn.type_enum()
    pos_payment_txn = Gtxn[14]

    Assert(
        And(
            Btoi(oracle_round) >= Minus(current_round, Int(4)),
            Btoi(oracle_round) <= current_round
        )
    )

    return Seq([
        oraclePubKey,
        Assert(oraclePubKey.hasValue()),
        product_id_data_verify.store(
            Concat(product_id, product_id_price, collection_type, collection_name)),  # collection_type could be null if the product is not connected to a collection
        If(merchant_paymentType == TxnType.Payment).Then(

            payment_type_data_verify.store(
                Concat(Bytes("L1"), merchant_address)),

            oracle_data_verify.store(
                Concat(
                    product_id_price,
                    Bytes("L1"),
                    Itob(Add(merchant_payment_txn.amount(),
                         pos_payment_txn.amount())),
                    oracle_round,
                )),

            Assert(Ed25519Verify_Bare(payment_type_data_verify.load(),
                                      payment_type_signature, merchant_pubkey)),

            Assert(Ed25519Verify_Bare(oracle_data_verify.load(),
                                      oracle_data_signature, oraclePubKey.value())),

            Assert(Ed25519Verify_Bare(
                product_id_data_verify.load(), product_id_signature, merchant_pubkey)),

            If(collection_type == Bytes("phygital")).Then(
                phygital_mint(),
                verify_payments()
            ).ElseIf(collection_type == Bytes("tokengate")).Then(
                verify_tokengate(),
                verify_payments()
            ).ElseIf(collection_type == Bytes("tokengatephygital")).Then(
                phygital_mint(),
                verify_tokengate(),
                verify_payments()
            ).ElseIf(collection_type == Bytes("false")).Then(
                verify_payments()
            )

        ).ElseIf(merchant_paymentType == TxnType.AssetTransfer).Then(

            payment_type_data_verify.store(
                Concat(Itob(merchant_payment_txn.xfer_asset()), merchant_address)),

            oracle_data_verify.store(
                Concat(
                    product_id_price,
                    Itob(merchant_payment_txn.xfer_asset()),
                    Itob(Add(merchant_payment_txn.asset_amount(),
                         pos_payment_txn.asset_amount())),
                    oracle_round,
                )),

            Assert(Ed25519Verify_Bare(payment_type_data_verify.load(),
                                      payment_type_signature, merchant_pubkey)),

            Assert(Ed25519Verify_Bare(oracle_data_verify.load(),
                                      oracle_data_signature, oraclePubKey.value())),

            Assert(Ed25519Verify_Bare(
                product_id_data_verify.load(), product_id_signature, merchant_pubkey)),


            If(collection_type == Bytes("phygital")).Then(
                phygital_mint(),
                verify_payments()
            ).ElseIf(collection_type == Bytes("tokengate")).Then(
                verify_tokengate(),
                verify_payments()
            ).ElseIf(collection_type == Bytes("tokengatephygital")).Then(
                phygital_mint(),
                verify_tokengate(),
                verify_payments()
            ).ElseIf(collection_type == Bytes("false")).Then(
                verify_payments()
            )

        ),
    ])

Last updated