FA1.2 Lorentz

Создание контракта на базе стандарта токена FA1.2 Tezos блокчейна

Введение в lorentz-contract-param

lorentz-contract-metadata - является версией FA1.2 с метаданными FA2.

Больше информации по стандарту метаданных FA2 может быть найдено в TZIP-12.

Установите инструменты lorentz-contract-metadata следуя iинструкциям по установке lorentz-contract-metadata.

Создание смарт-контракта

Контракт стандарта FA1.2 должен быть инициализирован со следующими параметрами хранения:

Pair
  {}                   -- Empty ledger big_map
  (Pair
      "$ALICE_ADDRESS" -- Administrator address
      (Pair
          False        -- Is all activity currently paused? (no)
          0            -- Total supply of tokens
      )
  )

А также иметь встроенные мета-параметры:

  • symbol: string

  • name: string

  • decimals: nat, количество цифр после десятичной точки при выводе.

  • extras: map string string, все остальные мета-параметры

Важно отметить: метаданные FA2 также включают natзначение : token_id которое определено как 0 для контрактов с единственным токеном, таких как FA1.2

В этом примере мы будем использовать:

  • symbol: TOK

  • name: Token

  • decimals: 0

  • extras: {}

Вместо того, чтобы предоставлять параметры контракта в сыром виде на языке Michelson, мы можем использовать lorentz-contract-metadata, чтобы сгенерировать их.

Чтобы создать контракт, запустите следующий код:

$ tezos-client --wait none originate contract ManagedLedger \
  transferring 0 from $ALICE_ADDRESS running \
  "$(lorentz-contract-metadata Metadata print \
  --token-symbol "TOK" \
  --token-name "Token" \
  --token-decimals 0 \
  --oneline)" \
  --init "$(lorentz-contract-metadata Metadata init \
  --admin $ALICE_ADDRESS \
  --initial-ledger '[]')" --burn-cap 5.033 --force

Waiting for the node to be bootstrapped before injection...
Current head: BLoWu4vMmzZb (timestamp: 2020-03-31T19:35:39-00:00, validation: 2020-03-31T19:36:23-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 142649 units (will add 100 for safety)
Estimated storage: 5033 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'onnLanKjRG4E64eevGpPP2TFteheNoDEyy8uDMdZGHPgy18YWkC'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for onnLanKjRG4E64eevGpPP2TFteheNoDEyy8uDMdZGHPgy18YWkC to be included --confirmations 30 --branch BLoWu4vMmzZbwYkJG8VimgkLis2xS3YSFAMFi4jEuWJ9mHVmKP5
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.001259
    Expected counter: 623911
    Gas limit: 10000
    Storage limit: 0 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001259
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,150) ... +ꜩ0.001259
    Revelation of manager public key:
      Contract: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      Key: edpkuPTVBFtbYd6gZWryXypSYYq6g7FvyucwphoU78T1vmGkbhj6qb
      This revelation was successfully applied
      Consumed gas: 10000
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.019169
    Expected counter: 623912
    Gas limit: 142749
    Storage limit: 5053 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.019169
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,150) ... +ꜩ0.019169
    Origination:
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      Credit: ꜩ0
      Script:
        {...}
        Initial storage:
          (Pair {} (Pair "tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm" (Pair False 0)))
        No delegate for this contract
        This origination was successfully applied
        Originated contracts:
          KT18apu7iDnqnUeXdMv3ZVjs81DTPWK6f1Me
        Storage size: 4776 bytes
        Updated big_maps:
          New map(735) of type (big_map address (pair nat (map address nat)))
        Paid storage size diff: 4776 bytes
        Consumed gas: 142649
        Balance updates:
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ4.776
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257

New contract KT18apu7iDnqnUeXdMv3ZVjs81DTPWK6f1Me originated.

Обратите внимание, что мы сокращаем большое содержимое скрипта с помощью {...}

Создайте переменную для нового адреса контракта:

FA12_ADDRESS=KT18apu7iDnqnUeXdMv3ZVjs81DTPWK6f1Me

Обратите внимание, что на включение наших операций в сеть блокчейнов может потребоваться некоторое время (обычно не более нескольких минут). Чтобы проверить статус операции, используйте её хеш для получения квитанции:

$ tezos-client get receipt for onnLanKjRG4E64eevGpPP2TFteheNoDEyy8uDMdZGHPgy18YWkC

Operation found in block: BLBBGyNZKoi7hrZeszBUmjtfeg8JcjdZMxpUyVTPj24cyyRJQeF (pass: 3, offset: 1)
Manager signed operations:
  From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
  Fee to the baker: ꜩ0.001259
  Expected counter: 623911
  Gas limit: 10000
  Storage limit: 0 bytes
  Balance updates:
    tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001259
    fees(tz1RomaiWJV3NFDZWTMVR2aEeHknsn3iF5Gi,150) ... +ꜩ0.001259
  Revelation of manager public key:
    Contract: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Key: edpkuPTVBFtbYd6gZWryXypSYYq6g7FvyucwphoU78T1vmGkbhj6qb
    This revelation was successfully applied
    Consumed gas: 10000
Manager signed operations:
  From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
  Fee to the baker: ꜩ0.019169
  Expected counter: 623912
  Gas limit: 142749
  Storage limit: 5053 bytes
  Balance updates:
    tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.019169
    fees(tz1RomaiWJV3NFDZWTMVR2aEeHknsn3iF5Gi,150) ... +ꜩ0.019169
  Origination:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Credit: ꜩ0
    Script:
      {...}
      Initial storage:
        (Pair {} (Pair "tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm" (Pair False 0)))
      No delegate for this contract
      This origination was successfully applied
      Originated contracts:
        KT18apu7iDnqnUeXdMv3ZVjs81DTPWK6f1Me
      Storage size: 4776 bytes
      Updated big_maps:
        New map(735) of type (big_map address (pair nat (map address nat)))
      Paid storage size diff: 4776 bytes
      Consumed gas: 142649
      Balance updates:
        tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ4.776
        tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257

Просмотры

Когда параметр контракта имеет не единичный тип возврата, например Get Total Supply, который возвращает общее количество токенов, сам контракт должен иметь возможность сохранять результат в каком-то месте. Например, другой контракт может принимать значение результата.

Для следующих примеров нам нужны контракты, принимающие значения address, natи token_metadata:

Для nat

$ tezos-client --wait none originate contract nat_storage transferring 0 \
  from $ALICE_ADDRESS running "{ parameter nat ; storage nat ; code { CAR ; NIL operation ; PAIR } }" \
  --init 0 --burn-cap 0.295

Waiting for the node to be bootstrapped before injection...
Current head: BKspjAccRQML (timestamp: 2020-03-31T19:40:49-00:00, validation: 2020-03-31T19:41:12-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 10909 units (will add 100 for safety)
Estimated storage: 295 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'onfjhheM6UMKwGYbr93a1XiJMEFUa4GyCgxfWJUvZrdGQVrL5RC'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for onfjhheM6UMKwGYbr93a1XiJMEFUa4GyCgxfWJUvZrdGQVrL5RC to be included --confirmations 30 --branch BKspjAccRQMLX8JFRtGUzRzenRnBStZiyPWigNihmUmWq3nwyf1
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.001368
    Expected counter: 623913
    Gas limit: 11009
    Storage limit: 315 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001368
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,150) ... +ꜩ0.001368
    Origination:
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      Credit: ꜩ0
      Script:
        { parameter nat ; storage nat ; code { CAR ; NIL operation ; PAIR } }
        Initial storage: 0
        No delegate for this contract
        This origination was successfully applied
        Originated contracts:
          KT1CTP1Bm1DvWCfeDibe8p5EDAAUa4XX4c34
        Storage size: 38 bytes
        Paid storage size diff: 38 bytes
        Consumed gas: 10909
        Balance updates:
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.038
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257

New contract KT1CTP1Bm1DvWCfeDibe8p5EDAAUa4XX4c34 originated.

Для address

$ tezos-client --wait none originate contract address_storage transferring 0 \
  from $ALICE_ADDRESS running "{ parameter address ; storage address ; code { CAR ; NIL operation ; PAIR } }" \
  --init "\"$ALICE_ADDRESS\"" --burn-cap 0.32

Waiting for the node to be bootstrapped before injection...
Current head: BKveReSTZqs9 (timestamp: 2020-03-31T19:46:17-00:00, validation: 2020-03-31T19:46:29-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 11314 units (will add 100 for safety)
Estimated storage: 320 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'oo8CFWkqaRuV4UGm6Ng87WJNYnU3q4YjC1txQcngF4BiF2URQ1V'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for oo8CFWkqaRuV4UGm6Ng87WJNYnU3q4YjC1txQcngF4BiF2URQ1V to be included --confirmations 30 --branch BKveReSTZqs9u1hCQzubvS2zm5c3vpeRjxNHnphpsULhNgwjgAZ
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.001448
    Expected counter: 623914
    Gas limit: 11414
    Storage limit: 340 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001448
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,150) ... +ꜩ0.001448
    Origination:
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      Credit: ꜩ0
      Script:
        { parameter address ;
          storage address ;
          code { CAR ; NIL operation ; PAIR } }
        Initial storage: "tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm"
        No delegate for this contract
        This origination was successfully applied
        Originated contracts:
          KT1LHvWNJhjGBehhNjd6BeNd1bzJkxhDd4fJ
        Storage size: 63 bytes
        Paid storage size diff: 63 bytes
        Consumed gas: 11314
        Balance updates:
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.063
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257

New contract KT1LHvWNJhjGBehhNjd6BeNd1bzJkxhDd4fJ originated.

Для token_metadata

Сначала определим:

TOKEN_METADATA_TYPE="(list (pair (nat %token_id) (pair (string %symbol) (pair (string %name) (pair (nat %decimals) (map %extras string string))))))"
$ tezos-client --wait none originate contract metadata_storage transferring 0 \
  from $ALICE_ADDRESS running "{ parameter $TOKEN_METADATA_TYPE ; storage $TOKEN_METADATA_TYPE ; code { CAR ; NIL operation ; PAIR } }" \
  --init '{Pair 0 (Pair "SYMBOL" (Pair "NAME" (Pair 0 {})))}' --burn-cap 0.493 --force

Waiting for the node to be bootstrapped before injection...
Current head: BLFoMNaKmThy (timestamp: 2020-03-31T20:40:53-00:00, validation: 2020-03-31T20:41:04-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 14859 units (will add 100 for safety)
Estimated storage: 493 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'opBNgPdvWG6siEEZTFdZXJgpm6gVF6SeZLjR7HJwab2BFjoPoWY'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for opBNgPdvWG6siEEZTFdZXJgpm6gVF6SeZLjR7HJwab2BFjoPoWY to be included --confirmations 30 --branch BLFoMNaKmThye5b5qa5yJA2hzNWNhtu6c1wvz84xCg3d3oaa3Pg
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.001961
    Expected counter: 623925
    Gas limit: 14959
    Storage limit: 513 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001961
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,150) ... +ꜩ0.001961
    Origination:
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      Credit: ꜩ0
      Script:
        { parameter
            (list (pair (nat %token_id)
                        (pair (string %symbol)
                              (pair (string %name) (pair (nat %decimals) (map %extras string string)))))) ;
          storage
            (list (pair (nat %token_id)
                        (pair (string %symbol)
                              (pair (string %name) (pair (nat %decimals) (map %extras string string)))))) ;
          code { CAR ; NIL operation ; PAIR } }
        Initial storage: { Pair 0 (Pair "SYMBOL" (Pair "NAME" (Pair 0 {}))) }
        No delegate for this contract
        This origination was successfully applied
        Originated contracts:
          KT1MRPDw2zXGPdL8CrzSaFS9jiqUDM8tpPNn
        Storage size: 236 bytes
        Paid storage size diff: 236 bytes
        Consumed gas: 14859
        Balance updates:
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.236
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257

New contract KT1MRPDw2zXGPdL8CrzSaFS9jiqUDM8tpPNn originated.

Примечание: вам может потребоваться установить/увеличить предел записи, чтобы разрешить создание контракта(ов), например:

$ tezos-client --wait none originate contract address_storage transferring 0 \
  from $ALICE_ADDRESS running "{ parameter address ; storage address ; code { CAR ; NIL operation ; PAIR } }" \
  --init "\"$ALICE_ADDRESS\"" --burn-cap 0.0001 --dry-run

Waiting for the node to be bootstrapped before injection...
Current head: BLY4388F8VTU (timestamp: 2019-08-30T17:03:46-00:00, validation: 2019-08-30T17:04:08-00:00)
Node is bootstrapped, ready for injecting operations.
Fatal error:
  The operation will burn ꜩ0.32 which is higher than the configured burn cap (ꜩ0.0001).
   Use `--burn-cap 0.32` to emit this operation.

Затем с помощью tezos-client get receipt for [Operation hash] для каждого хеша операции, сохранить адреса контрактов в переменных:

NAT_STORAGE_ADDRESS="KT1.."
ADDRESS_STORAGE_ADDRESS="KT1.."
METADATA_STORAGE_ADDRESS="KT1.."

Затем вы можете получить доступ к сохраненным значениям с помощью следующих двух команд для natи addressсоответственно:

$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS

0

$ tezos-client get contract storage for $ADDRESS_STORAGE_ADDRESS

"tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm"

Взаимодействия с помощью тезос-клиента

Команды для взаимодействия с нашим экземпляром контракта ManagedLedger с использованием tezos-client и lorentz-contract-param следуют одному и тому же шаблону с изменением только нескольких параметров в зависимости от того, какую точку входа в контракт мы вызываем. На примере getTotalSupply вызов будет выглядеть так:

$ tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $FA12_ADDRESS \
  --arg "$(lorentz-contract-metadata \
  Metadata getTotalSupply \
  --callback-contract $NAT_STORAGE_ADDRESS)"

Давайте запишем шаблон в функцию оболочки:

$ fa12(){tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $FA12_ADDRESS --burn-cap 0.5 --arg "$(lorentz-contract-metadata Metadata $@;)"}

Обратите внимание, что здесь мы также устанавливаем --burn-cap заглушку.

Получение общего предложения через getTotalSupply

Определив функцию fa12, мы можем теперь вызвать точку входа контракта getTotalSupply следующим образом:

$ fa12 getTotalSupply --callback-contract $NAT_STORAGE_ADDRESS

Вывод этой команды выглядит так:

Waiting for the node to be bootstrapped before injection...
Current head: BLkmHajH44cY (timestamp: 2020-03-31T19:51:39-00:00, validation: 2020-03-31T19:52:00-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 132442 units (will add 100 for safety)
Estimated storage: no bytes added
Operation successfully injected in the node.
Operation hash is 'oothedERdD6hkD45S9ncrnS3u6ienY3px92iSyfjAd4ijLtUjqs'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for oothedERdD6hkD45S9ncrnS3u6ienY3px92iSyfjAd4ijLtUjqs to be included --confirmations 30 --branch BLkmHajH44cYRFJzTqmdBnh3efUHGQnjZyKbjAmBB6bgeQbuXzV
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.013564
    Expected counter: 623915
    Gas limit: 132542
    Storage limit: 0 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.013564
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,150) ... +ꜩ0.013564
    Transaction:
      Amount: ꜩ0
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      To: KT18apu7iDnqnUeXdMv3ZVjs81DTPWK6f1Me
      Parameter: (Left (Right (Right (Right (Pair Unit "KT1CTP1Bm1DvWCfeDibe8p5EDAAUa4XX4c34")))))
      This transaction was successfully applied
      Updated storage:
        (Pair 735 (Pair 0x0000aad02222472cdf9892a3011c01caf6407f027081 (Pair False 0)))
      Storage size: 4776 bytes
      Consumed gas: 121125
    Internal operations:
      Transaction:
        Amount: ꜩ0
        From: KT18apu7iDnqnUeXdMv3ZVjs81DTPWK6f1Me
        To: KT1CTP1Bm1DvWCfeDibe8p5EDAAUa4XX4c34
        Parameter: 0
        This transaction was successfully applied
        Updated storage: 0
        Storage size: 38 bytes
        Consumed gas: 11317

Все команды в случае успеха дают одинаковый вывод, поэтому мы опускаем его в следующих примерах.

Значение общего количества токенов будет записано в простом хранилище контракта по адресу NAT_STORAGE_ADDRESS, который мы можем увидеть с помощью следующей команды (как только сеть tezos включит наши операции):

$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS

0

Получение данных администратора

Чтобы получить адрес текущего администратора, сначала поместите его в контракт ADDRESS_STORAGE_ADDRESS:

$ fa12 getAdministrator --callback-contract $ADDRESS_STORAGE_ADDRESS

Как и в случае с NAT_STORAGE_ADDRESS, мы можем получить доступ к результату, используя get contract storage for и убедиться, что он соответствует адресу Алисы, используя echo $ ALICE_ADDRESS:

$ tezos-client get contract storage for $ADDRESS_STORAGE_ADDRESS

"tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm"

$ echo $ALICE_ADDRESS

tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm

Получение баланса

Чтобы получить баланс токенов для определенного адреса (хранится в контракте NAT_STORAGE_ADDRESS) используйте:

$ fa12 getBalance --owner $ALICE_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS

Затем мы можем получить доступ к результату, используя:

$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS

0

Получение метаданных

Чтобы получить метаданные токена для конкретного контракта в стиле FA1.2 + FA2 (хранящегося в METADATA_STORAGE_ADDRESS) используйте:

$ fa12 getMetadata --callback-contract $METADATA_STORAGE_ADDRESS

Затем мы можем получить доступ к результату, используя:

$ tezos-client get contract storage for $METADATA_STORAGE_ADDRESS

{ Pair 0 (Pair "TOK" (Pair "Token" (Pair 0 {}))) }

Получение разрешений

Чтобы получить разрешение Боба на снятие средств со счета Алисы, где адрес Боба - BOB_ADDRESS используйте:

$ fa12 getAllowance --owner $ALICE_ADDRESS --spender $BOB_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS

Затем мы можем получить доступ к результату, используя:

$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS

0

Перевод

Из GetBalanceвыше мы знаем, что у Aliceнет токенов.

Чтобы передать токены от Алисы Бобу, нам сначала нужно дать Алисе несколько токенов. Мы можем сделать это, выпустив 5 токенов и назначив их Алисе (см. Подраздел «Выпуск токена» ниже):

$ fa12 mint --value 5 --to $ALICE_ADDRESS

Чтобы передать 2 токена от Алисы Бобу:

$ fa12 transfer --value 2 --from $ALICE_ADDRESS --to $BOB_ADDRESS

Проверьте баланс Боба:

$ fa12 getBalance --owner $BOB_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS
$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS
2

Подтверждение операций

Чтобы Алиса разрешила Бобу снять до 2 токена с ее адреса:

$ fa12 approve --value 2 --spender $BOB_ADDRESS

Затем мы можем проверить полученное разрешение, используя:

$ fa12 getAllowance --owner $ALICE_ADDRESS --spender $BOB_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS
$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS
2

Если мы попытаемся установить другое разрешение (4) для снятия Бобом токенов со счета Алисы, мы потерпим неудачу:

$ fa12 approve --value 4 --spender $BOB_ADDRESS
...
At line 294 characters 85 to 93,
script reached FAILWITH instruction
with (Pair "UnsafeAllowanceChange" 2)

Контракт FA1.2 запрещает прямое изменение разрешения с ненулевого значения на другое ненулевое значение, чтобы предотвратить известную уязвимость к изменению разрешений.

Итак, чтобы сделать такое изменение разрешения возможным, нам нужно сначала установить его в 0:

$ fa12 approve --value 0 --spender $BOB_ADDRESS

а затем установить новое значение 4:

$ fa12 approve --value 4 --spender $BOB_ADDRESS

теперь операция не приведет к провалу.

Обратите внимание, что, в целом, это не совсем безопасно, потому что Боб мог потратить часть полученного от Алисы в промежутке времени между транзакцией, когда мы сначала установили разрешение на 2, и той, где оно было установлено в 0.

Чтобы правильно рассчитать новое значение, отличное от 0, нам нужно было бы просканировать все транзакции, произошедшие между этими двумя, но здесь мы, для простоты, предположим, что их не было.

Теперь мы можем снова проверить разрешение и увидеть, что оно изменилось:

$ fa12 getAllowance --owner $ALICE_ADDRESS --spender $BOB_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS
$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS
4

Выпуск токена

Чтобы выпустить 5 токенов и назначить их Алисе:

$ fa12 mint --value 5 --to $ALICE_ADDRESS
$ fa12 getBalance --owner $ALICE_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS
$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS
5

Сжигание токена

Если вы пошагово следовали этому руководству, на данный момент в учетной записи Боба должно быть 3 токена. Если этого не произошло, добавьте хотя бы 1 с помощью Transfer или Mint.

Перед сжиганием мы сначала добавляем 2 токена на аккаунт Боба:

$ fa12 mint --value 2 --to $BOB_ADDRESS

Мы можем гарантировать, что у Боба есть как минимум 3 токена, используя:

$ fa12 getBalance --owner $BOB_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS
$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS
5

Наконец, мы можем сжечь 2 токена Боба, используя:

$ fa12 burn --value 2 --from $BOB_ADDRESS

И тогда мы можем подтвердить, что два токена были вычтены из аккаунта Боба:

$ fa12 getBalance --owner $BOB_ADDRESS --callback-contract $NAT_STORAGE_ADDRESS
$ tezos-client get contract storage for $NAT_STORAGE_ADDRESS
3

Приостановка контракта

Чтобы приостановить контракт:

$ fa12 setPause --paused True

Мы можем проверить, приостановлен ли контракт, используя:

$ tezos-client get contract storage for $FA12_ADDRESS
Pair 0 (Pair "tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm" (Pair True 7))

Значение True указывает, что он приостановлен, значение False указывает, что он не приостановлен.

Передачи и подтверждения отключены, пока контракт приостановлен. Попробуйте:

$ fa12 transfer --value 1 --from $ALICE_ADDRESS --to $BOB_ADDRESS

Команда выдает следующий результат (для краткости опуская включенный в контракт код Майкельсона):

Node is bootstrapped, ready for injecting operations.
This simulation failed:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0
    Expected counter: 32
    Gas limit: 800000
    Storage limit: 60000 bytes
    Transaction:
      Amount: ꜩ0
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      To: KT1P33YQj5LQGBAYxvpXCsa6v2BXJ8N4i6PF
      Parameter: (Left (Left (Left (Pair "tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm"
                                         (Pair "tz1aSkwEot3L2kmUvcoxzjMomb9mvBNuzFK6" 1)))))
      This operation FAILED.

Runtime error in contract KT1P33YQj5LQGBAYxvpXCsa6v2BXJ8N4i6PF:
  001: { parameter
...
  585:                          NIL operation ;
  586:                          PAIR } } } } } }
At line 23 characters 87 to 95,
script reached FAILWITH instruction
with (Pair "TokenOperationsArePaused" Unit)
Fatal error:
  transfer simulation failed

Чтобы возобновить контракт:

$ fa12 setPause --paused False
$ tezos-client get contract storage for $FA12_ADDRESS

Pair 0 (Pair "tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm" (Pair False 7))

Установка нового администратора

Чтобы сделать Боба новым администратором:

$ fa12 setAdministrator --new-administrator-address $BOB_ADDRESS

Мы можем убедиться, что администратор был обновлен, используя:

$ fa12 getAdministrator --callback-contract $ADDRESS_STORAGE_ADDRESS
$ tezos-client get contract storage for $ADDRESS_STORAGE_ADDRESS
"tz1RwoEdg4efDQHarsw6aKtMUYvg278Gv1ir"
$ echo $BOB_ADDRESS

tz1RwoEdg4efDQHarsw6aKtMUYvg278Gv1ir

Наша функция оболочки fa12 настроена для вызова операций с использованием $ALICE_ADDRESS, так что теперь, когда $ALICE_ADDRESS больше не является администраторским, попытки вызвать точки входа администратора с этого адреса потерпят неудачу:

$ fa12 mint --value 5 --to $ALICE_ADDRESS
...
  586:                          PAIR } } } } } }
At line 447 characters 86 to 94,
script reached FAILWITH instruction
with (Pair "SenderIsNotAdmin" Unit)

Взаимодействие с использованием PyTezos

Установка PyTezos

Если вы используете Debian или Ubuntu Linux, установите зависимости с помощью apt:

sudo apt install libsodium-dev libsecp256k1-dev libgmp-dev

В Arch Linux установите эти пакеты с помощью pacman:

sudo pacman libsodium libsec256k1 gmp

Вам также может потребоваться установить python-wheel

В противном случае, если у вас Mac OS, установите пакеты с помощью brew:

brew tap cuber/homebrew-libsecp256k1
brew install libsodium libsecp256k1 gmp

Затем установите PyTezos с помощью pip3:

pip3 install pytezos

Создание контракта

Предполагая, что $ALICE_ADDRESS определен, мы можем создать копию FA1.2 почти так же, как с lorentz-contracts.

Примечание: См. Руководство по настройке клиента, чтобы создать кошелек и определить $ALICE_ADDRESS.

Начнем с открытия python3, установки key и shell и указания fa12 в качестве контракта:

Примечание: замените ~/Downloads/tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr.json на путь к файлу .json вашего кошелька.

$ python3
Python 3.7.4 (default, Sep  7 2019, 18:27:02)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from pytezos import pytezos
>>> pytezos = pytezos.using(key='~/Downloads/tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr.json', shell='babylonnet')

>>> alice_address = 'tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr'
>>> bob_address = 'tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm'
>>> nat_storage_address = 'KT1J4mhVAaMYAPC4aPEkhC9i48PHBHxavkJ2'

Затем мы определяем Contract из копии ManagedLedger.tz с аннотациями:

>>> from pytezos import Contract
>>> import requests

>>> contract_url = 'https://gitlab.com/tzip/tzip/raw/16ca4fbb60f2ab52958136b76a1d12b342beba58/Proposals/TZIP-0007/ManagedLedger.tz'
>>> fa12src = Contract.from_michelson(requests.get(contract_url).text)

Нам нужно создать начальное хранилище для создания контракта.

Чтобы помочь с этим, мы можем просмотреть схему хранилища контракта:

>>> fa12src.storage
<pytezos.michelson.contract.ContractStorage object at 0x10d984590>

$storage:
    {
      "ledger": { $address : $ledger_item , ... }  /* big_map */,
      "admin": $address,
      "paused": bool,
      "totalSupply": $nat
    }

$ledger_item:
    {
      "balance": $nat,
      "approvals": { $address : $nat , ... }
    }

$nat:
    int  /* Natural number */

$address:
    string  /* Base58 encoded `tz` or `KT` address */


Helpers
.big_map_decode()
.big_map_diff_decode()
.big_map_diff_encode()
.big_map_id()
.big_map_init()
.big_map_query()
.decode()
.default()
.encode()

Затем мы выбираем начальные значения хранилища и кодируем их для подготовки к созданию контракта:

>>> init_storage = fa12src.storage.encode({
    ...:  "ledger": {},
    ...:  "admin": pytezos.key.public_key_hash(),
    ...:  "paused": False,
    ...:  "totalSupply": 0
    ...: } )

Затем мы создаем контракт:

>>> origination_op = pytezos.origination(script=dict(code=fa12src.code, storage=init_storage)).autofill().sign().inject()
>>> origination_hash = origination_op['hash']
>>> origination_hash
'opXxLwE3j9ZY9Rv99Pomh6u7SonKAoywzpU6KkdWtFryUhBbXdP'

Однако создание контракта не возвращает адрес полученного контракта, поэтому нам нужно найти нашу завершенную операцию в сети и получить из нее адрес контракта:

>>> opg = pytezos.shell.blocks[-5:].find_operation(origination_hash)
>>> contract_id = opg['contents'][0]['metadata']['operation_result']['originated_contracts'][0]
>>> contract_id
'KT1GV7wkUgZpEznQ48VR1UUSgXAU5Lk1SfpH'

>>> fa12 = pytezos.contract(contract_id)

Примечание: команда find_operation может завершиться ошибкой, если операция еще не была обработана:

>>> opg = pytezos.shell.blocks[-5:].find_operation(origination_op)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/pytezos/tools/docstring.py", line 67, in __call__
    return method(self.class_instance, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/pytezos/rpc/search.py", line 207, in find_operation
    raise StopIteration(operation_group_hash)
StopIteration: oonhxpbH9Jc7fpbjfzvfbetppEBnjUTFmkbziVFV3B5KhjVdzpd

Просмотр схемы контракта

Мы можем просмотреть схему параметров контракта, чтобы узнать, какие точки входа поддерживает контракт и каковы их аргументы:

>>> fa12.contract.parameter
<pytezos.michelson.contract.ContractParameter object at 0x10ce5d910>

$parameter:
    { "transfer": $transfer } ||
    { "approve": $approve } ||
    { "getAllowance": [ $address , $address , $contract (nat) ] } ||
    { "getBalance": [ $address , $contract (nat) ] } ||
    { "getTotalSupply": [ $unit , $contract (nat) ] } ||
    { "setPause": bool  /* setPause */ } ||
    { "setAdministrator": $address  /* setAdministrator */ } ||
    { "getAdministrator": [ $unit , $contract (address) ] } ||
    { "mint": $mint } ||
    { "burn": $burn }

$burn:
    {
      "from": $address,
      "value": $nat
    }

$mint:
    {
      "to": $address,
      "value": $nat
    }

$approve:
    {
      "spender": $address,
      "value": $nat
    }

$transfer:
    {
      "from": $address,
      "to": $address,
      "value": $nat
    }

$contract:
    string  /* Base58 encoded `KT` address */

$nat:
    int  /* Natural number */

$address:
    string  /* Base58 encoded `tz` or `KT` address */

$unit:
    None /* Void */


Helpers
.decode()
.encode()
.entries()

Взаимодействие с FA1.2

Наконец, используя схему параметров, мы можем выполнить передачу, используя следующие шаги:

  • Выпуск 5 токенав на alice_address

  • Перевод 3 токенов от alice_address к bob_address

  • Хранение баланса bob_address в nat_storage_address

  • Получить значение, которое храниться в nat_storage_address

>>> op = fa12.mint(to=alice_address, value=5).inject()
>>> op['hash']
'opDS6FUYmzXBRpX1DxpnucWBrcyEvCmAsSdjmHJMNpf7xQhGsRW'

>>> op = fa12.transfer(**{'from': alice_address, 'to': bob_address, 'value': 3}).inject()
>>> op['hash']
'ooQRsxqkV3vEtaDdarMzvzFuZLeKe6qfJkZEx9PntzqHGxVo8FU'

>>> op = fa12.getBalance(bob_address, nat_storage_address).inject()
>>> op['hash']
'opUVaphfSFgeUTACVmspr6bXrY82RLJ4mSf4DgT2kNZ6SiEcuh6'

>>> pytezos.contract(nat_storage_address).storage()
3

Примечание. Почему .transfer(**{'from': ..}) вместо .transfer(from=..)? В Python from является ключевым словом и не может использоваться для указания аргумента, поэтому мы используем **{..} для преобразования словаря в аргументы ключевого слова.

Исправление проблем

Counter _ already used

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

$ tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $FA12_ADDRESS --arg ..

Waiting for the node to be bootstrapped before injection...
Current head: BMe8VmYBa1Ye (timestamp: 2019-08-12T15:34:56-00:00, validation: 2019-08-12T15:35:00-00:00)
Node is bootstrapped, ready for injecting operations.
Counter 565668 already used for contract tz1QLne6uZFxPRdRfJG8msx5RouENpJoRsfP (expected 565669)
Fatal error:
  transfer simulation failed
$ tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $FA12_ADDRESS --arg ..

Waiting for the node to be bootstrapped before injection...
Current head: BL7QrQjGhkut (timestamp: 2019-08-12T15:39:26-00:00, validation: 2019-08-12T15:39:45-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 212314 units (will add 100 for safety)
Estimated storage: no bytes added
Unregistred error:
  { "kind": "generic",
    "error":
      "Error while applying operation op1imCEMKFm7bTN9cwX4uoKPb6FjHJDv6NCkWKGVE7srh4XN6UP:\nbranch refused (Error:\n
      Counter 565670 already used for contract tz1QLne6uZFxPRdRfJG8msx5RouENpJoRsfP (expected 565671)\n)" }
Fatal error:
  transfer simulation failed

Чтобы исправить эту ошибку вы можете предпринять одно из двух:

  • Дождитесь включения операции

  • Запустите tezos-client wait for [Operation Hash] to be includedс зависимыми операциями Operation Hash прежде чем продолжить

    • В качестве альтернативы вы можете запустить: `tz get receipt for

      [Operation Hash]`

Higher than the configured burn cap

Эта ошибка может возникнуть, если параметр --burn-cap не указан или установлен слишком низким для текущей операции:

$ tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $FA12_ADDRESS --arg ..

Waiting for the node to be bootstrapped before injection...
Current head: BLBsvLowXAPf (timestamp: 2019-08-12T15:41:56-00:00, validation: 2019-08-12T15:42:45-00:00)
Node is bootstrapped, ready for injecting operations.
Fatal error:
  The operation will burn ꜩ0.021 which is higher than the configured burn cap (ꜩ0).
   Use `--burn-cap 0.021` to emit this operation.

Чтобы исправить, замените или добавьте --burn-cap с данной рекомендацией (в данном случае --burn-cap 0.021)

Материалы разработаны TQ Tezos переведены на русский язык Tezos Ukraine

Last updated