FA2-SmartPy
В этом руководстве показано, как взаимодействовать с «FA2-SmartPy» реализацией стандарта FA2 в некоторых распространенных сценариях использования. В первой части используются команды
tezos-client
для работы с основными передачами и запросами. Вторая часть идет дальше: она использует интерфейс командной строки fatoo
для пакетной передачи и использует механизм «оператора» для делегирования прав передачи.Это предполагает, что у вас правильно настроен
tezos-client
для взаимодействия с Carthagenet или с «полной» песочницей.Для этой части требуется 4 аккаунта, с несколькими импортироваными в
tezos-client
ꜩ . Аккаунты: administrator
, originator
, alice
иbob
.Согласно нашему руководству по песочнице мы используем
alice
также как originator
и administrator
: $ tezos-client import secret key alice \
unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq \
--force
tezos-client import secret key originator \
unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq \
--force
tezos-client import secret key administrator \
unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq \
--force
tezos-client import secret key bob \
unencrypted:edsk3RFfvaFaxbHx8BMtEW1rKQcPtDML3LXjNqMNLCzC3wLC1bWbAt \
--force
FA2-SmartPy использует средства метапрограммирования SmartPy для предоставления более одного контракта Майкельсона. Такие контракты также известны как «сборки». Некоторые сборки доступны по адресу https://gitlab.com/smondet/fa2-smartpy/-/tree/master/michelson, далее в руководстве будет описание различных сборок.
Скачиваем сборку «по умолчанию»:
$ wget -O fa2_default.tz \
'https://gitlab.com/smondet/fa2-smartpy/-/raw/a58e9f11/michelson/20200724-170337+0000_8cee712_contract.tz'
Создание работает так же, как и для любого контракта, нам нужен приведенный выше код, несколько ꜩ и выражение Майкельсона для инициализации хранилища. В нашем случае это должно выглядеть так:
(Pair
(Pair "<admin-pkh>" (Pair <nb-of-tokens> <ledger-big-map>))
(Pair (Pair Unit <operators-big-set>)
(Pair <paused> <tokens-big-map>)))
Ожидается, что
<nb-of-tokens>
является кардиналом карты <tokens-big-map>
, а в <ledger-big-map>
используются только «известные» токены. Чтобы правильно поддерживать все инварианты, рекомендуется инициализировать хранилище пустым и использовать точку входа %mint
для заполнения контракта.Создадим такой не приостановленный пустой контракт при установке адреса
administrator
: $ tezos-client originate contract myfa2 \
transferring 0 from originator \
running fa2_default.tz \
--init '(Pair (Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" (Pair 0 {})) (Pair (Pair Unit {}) (Pair False {})))' \
--burn-cap 10 \
--force --no-print-source
┃ Node is bootstrapped.
┃ Estimated gas: 130373 units (will add 100 for safety)
┃ Estimated storage: 4447 bytes added (will add 20 for safety)
┃ Operation successfully injected in the node.
┃ Operation hash is 'onosZKPHVN5dGy7LGKX2NV3Tyy3Dyg7qMNeGAn1Eqp7Mwx8sazk'
┃ Waiting for the operation to be included...
┃ Operation found in block: BM31KMRfkmiDDBMfaq9tCQe5TM6Xhxp3D8XseDWMynG7k81S9q8 (pass: 3, offset: 0)
┃
┃ ...
┃
┃ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.257
┃ New contract KT1Wf2sNVoosmXZqXEppsPZkS4BNAUL7hjTL originated.
┃ The operation has only been included 0 blocks ago.
┃ We recommend to wait more.
┃ Use command
┃ tezos-client wait for onosZKPHVN5dGy7LGKX2NV3Tyy3Dyg7qMNeGAn1Eqp7Mwx8sazk to be included --confirmations 30 --branch BMHcbMLmK3avi1ntw9rtcMgyPFjzyUxXhf5a8zDdjKM8eqJHenx
┃ and/or an external block explorer.
┃ Contract memorized as myfa2.
Здесь мы хотим сделать перевод в качестве
administrator
, установленного в предыдущем разделе.Точка входа для выпуска не имеет жесткой стандартизации в спецификации FA2, для fa2-smartpy она должна выглядеть так:
(Pair (Pair "<address>" <amount>) (Pair "<token-symbol>" <token-id>))
Сборка по умолчанию предполагает, что идентификаторы токенов являются последовательными натуральными числами (0, 1, 2, ...), если из-за какого-то конкретного ограничения пользователю требуются произвольные идентификаторы токенов, в FA2-SmartPy есть опция сборки для создания такого контракта ( см. документацию).
Например, давайте, как
administrator
, выпустим 100 TK0
токенов на счет alice
: $ tezos-client transfer 0 from administrator to myfa2 \
--entrypoint mint \
--arg '(Pair (Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" 100) (Pair "TK0" 0))' \
--burn-cap 3
┃ Node is bootstrapped.
┃ Estimated gas: 113946 units (will add 100 for safety)
┃ Estimated storage: 163 bytes added (will add 20 for safety)
┃ Operation successfully injected in the node.
┃ Operation hash is 'onpcARPLVMjXqRfjFxyaZFGnpbCdsP2uSVKQwMiBHie4ujRf7fe'
┃ Waiting for the operation to be included...
┃ Operation found in block: BMCwBfn9B2E5zmrNfAu3z4rwoTo3h2DhDjTFgsn4BvTB21Xguff (pass: 3, offset: 0)
┃
┃ ...
┃
┃ Consumed gas: 113946
┃ Balance updates:
┃ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.163
┃ The operation has only been included 0 blocks ago.
┃ We recommend to wait more.
┃ Use command
┃ tezos-client wait for onpcARPLVMjXqRfjFxyaZFGnpbCdsP2uSVKQwMiBHie4ujRf7fe to be included --confirmations 30 --branch BM31KMRfkmiDDBMfaq9tCQe5TM6Xhxp3D8XseDWMynG7k81S9q8
┃ and/or an external block explorer.
Точка входа передачи в FA2 «группируется» на двух уровнях, т.е. один контрактный вызов содержит список элементов передачи, каждый элемент передачи является «адресом отправителя» и списком исходящих транзакций:
{
Pair "<from-1>" {Pair "<to-1>" (Pair <token-id-1> <amount-1>)} ;
Pair "<from-2>" {Pair "<to-2>" (Pair <token-id-2> <amount-2>) ; Pair "<to-3>" (Pair <token-id-3> <amount-3>)} ;
...
}
Здесь мы, как
alice
, переводим 5 из наших 100 TK0 на аккаунт bob
: $ tezos-client transfer 0 from alice to myfa2 \
--entrypoint transfer \
--arg '{ Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" {Pair "tz1aSkwEot3L2kmUvcoxzjMomb9mvBNuzFK6" (Pair 0 5)} }' \
--burn-cap 3
┃ Node is bootstrapped.
┃ Estimated gas: 116015 units (will add 100 for safety)
┃ Estimated storage: 67 bytes added (will add 20 for safety)
┃ Operation successfully injected in the node.
┃ Operation hash is 'ontGCqsFh1uSDp5vmucU6EJxkivXw6bto2DN8LRekhXdo6WSTjK'
┃ Waiting for the operation to be included...
┃ Operation found in block: BLgT1CrszWaeEnxo4ncHWHwRZ1g39ig1NxT2zQB8AtCaFKhijnn (pass: 3, offset: 0)
┃ This sequence of operations was run:
┃
┃ ...
┃
┃ Consumed gas: 116015
┃ Balance updates:
┃ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.067
┃ The operation has only been included 0 blocks ago.
┃ We recommend to wait more.
┃ Use command
┃ tezos-client wait for ontGCqsFh1uSDp5vmucU6EJxkivXw6bto2DN8LRekhXdo6WSTjK to be included --confirmations 30 --branch BMCwBfn9B2E5zmrNfAu3z4rwoTo3h2DhDjTFgsn4BvTB21Xguff
┃ and/or an external block explorer.
В качестве примера взаимодействия с big-картами в хранилище контрактов с помощью Michelson и
tezos-client
мы получаем баланс Алисы в токенах TK0.Нам нужен скрипт, который принимает тип хранилища контракта в качестве параметра (буквально копирует и вставляет) и использует Майкельсон для извлечения значения в карту
%ledger
; в этом случае мы просто отображаем его с инструкцией FAILWITH
, но можно было бы сделать гораздо больше, включая помещение в память (оставлено как упражнение для читателя ☺). Сохраним его как get-balance.tz
:parameter
(pair (pair (address %administrator)
(pair (nat %all_tokens) (big_map %ledger (pair address nat) nat)))
(pair (pair (unit %version_20200724_tzip_a57dfe86_contract)
(big_map %operators (pair (address %owner) (address %operator)) unit))
(pair (bool %paused)
(big_map %tokens
nat
(pair (nat %token_id)
(pair (string %symbol)
(pair (string %name) (pair (nat %decimals) (map %extras string string))))))))) ;
storage unit;
code
{
CAR ; # Get parameter
CAR ; # Get the pair (admin , _)
CDR ; # Get the pair (all_token, ledger)
CDR ; # Get %ledger
PUSH (pair address nat) (Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" 0);
GET ; # Get the value in the ledger at the above key
FAILWITH
};
В этом случае мы ожидаем сбоя команды
tezos-client
, поскольку мы хотим прочитать сообщение об ошибке: $ tezos-client run script get-balance.tz on storage Unit \
and input \
"$(tezos-client get contract storage for myfa2)"
‖
‖ ...
‖
‖ 20: GET ; # Get the value in the ledger at the above key
‖ 21: FAILWITH
‖ 22: };
‖ At line 21 characters 4 to 12,
‖ script reached FAILWITH instruction
‖ with (Some 95)
‖ Fatal error:
‖ error running script
Мы можем отчетливо видеть в значении ошибки (переданном в
FAILWITH
), что баланс alice
составляет 95 TK0 (100 выпущено минус 5 переведено в аккаунт bob
).В этом разделе мы используем интерфейс командной строки
fatoo
для некоторых сборок FA2-SmartPy. Вам нужно установить fatoo
по вашему $PATH
, или вы можете использовать Docker: $ fatoo --version
# or:
docker run -it --rm --entrypoint fatoo registry.gitlab.com/smondet/fa2-smartpy:a58e9f11-run --version
В приложении
fatoo
есть много команд, см. fatoo [subcommand] --help
. В то же время он находится в стадии разработки, поэтому не стесняйтесь отправлять вопросы и запросы функций в основном репозитории.Для настройки могут использоваться две переменные среды:
fatoo_root_path
: логи, выводfatoo_client
: более важный - это URI, описывающий, как настроитьtezos-client
и взаимодействовать с узлом
Смотрите команду
fatoo show-client-uri-documentation
:URI следует обычному шаблону:<scheme>://<host>:<port>/<path>?<options>
:
<scheme>
может бытьhttp
илиhttp
(--tls
вариант);<host>:<port>
определяет подключение к узлу;<path>
это закрытый ключ (URI) для учетной записи «спонсора», используется для оплаты горючего и храненияДоступные<options>
это:
bake=true
: используйте аккаунтfunder
запекать блоки после операций инъекции (полезно для «ручных» песочниц);wait=<INT>
: установите опцию--wait
дляtezos-client
(сколько блоков нужно ждать после инъекции операции);command=<STRING>
: используйте альтернативную команду дляtezos-client
.См., например, текущее значение по умолчанию:http://:2020/unencrypted:edsk3S7mCwuuMVS21jsYTczxBU4tgTbQp98J3YmTGcstuUxsrZxKYd?bake=true
.
Предполагая, что мы используем песочницу, мы можем настроить к лиента, используя закрытый ключ
alice
следующим образом:export fatoo_client='http://:20000/unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq?wait=0'
# Or, for docker, use:
alias fatoo='docker run -it -u "$UID" --network host -v "$PWD:/work" -w /work --rm -e fatoo_client="http://:20000/unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq?wait=0" --entrypoint fatoo registry.gitlab.com/smondet/fa2-smartpy:a58e9f11-run'
В приложении есть подкоманда
client
, которая просто правильно вызывает tezos-client
, их настройку можно проверить с помощью: $ fatoo client bootstrapped
┃ Node is bootstrapped.
Здесь мы создаем четыре пары ключей из мнемонических семян, которые будут использоваться в следующих разделах:
$ fatoo account-of-seed \
"the-only-administrator-of-the-contract" \
--output admin.csv
fatoo account-of-seed \
"the-0th-aka-first-owner" \
--output owner0.csv
fatoo account-of-seed \
"ready-owner-one" \
--output owner1.csv
fatoo account-of-seed \
"this-is-a-potential-token-owner-too" \
--output owner2.csv
Полученные CSV имеют тот же формат, что и flextesa, они содержат:
<phrase>,<pk>,<pkh>,<sk>
. См., например: $ echo "Public key hash: $(cut -d, -f 3 admin.csv)"
echo "Secret key: $(cut -d, -f 4 admin.csv)"
┃ Public key hash: tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe
┃ Secret key: unencrypted:edsk3ZAm4BwNkG2uUmCcA64BadPWuwNt16zZisnfcQEuvyStaBa6oG
Установим имена для всего этого:
$ export admin_pkh="$(cut -d, -f 3 admin.csv)"
export admin_sk="$(cut -d, -f 4 admin.csv)"
export owner0_pkh="$(cut -d, -f 3 owner0.csv)"
export owner0_sk="$(cut -d, -f 4 owner0.csv)"
export owner1_pkh="$(cut -d, -f 3 owner1.csv)"
export owner1_sk="$(cut -d, -f 4 owner1.csv)"
export owner2_pkh="$(cut -d, -f 3 owner2.csv)"
export owner2_sk="$(cut -d, -f 4 owner2.csv)"
Приложение содержит код для нескольких вариантов контракта:
$ fatoo list-contract-variants \
--details description --format markdown
┃ * `contract`: The default.
┃ * `dbg_contract`: The default in debug mode.
┃ * `baby_contract`: The default in Babylon mode.
┃ * `nolay_contract`: The default without right-combs.
┃ * `mutran_contract`: The default with mutez transfer entry-point.
┃ * `tokset_contract`: The default with non-consecutive token-IDs.
┃ * `perdesc_noops_contract`: The default without operators and with permissions-descriptor.
┃ * `perdesc_noops_dbg_contract`: The perdesc_noops_contract but in debug mode.
┃ * `single_contract`: The default for single-asset.
┃ * `single_mutran_contract`: The single-asset with mutez transfer entry-point.
┃ * `nft_mutran_contract`: The default in NFT mode with mutez transfer entry-point.
┃ * `lzep_contract`: The default with lazy-entry-points flag.
┃ * `lzepm_contract`: The default with lazy-entry-points-multiple flag.
┃ * `lzep_mutran_contract`: The default with mutez-transfer and lazy-entry-points flag.
┃ * `lzepm_mutran_contract`: The default with mutez-transfer and lazy-entry-points-multiple flag.
Можно сбросить код Майкельсона в файл (см.
fatoo get-code --help
), но в этом нет необходимости, поскольку можно напрямую создавать контракты из приложения. Давайте создадим mutran_contract
, полномасштабную реализацию FA2 с дополнительной точкой входа, которая позволяет администратору переводить средства, которые потенциально могут оказаться на балансе контракта. $ fatoo originate mutran_contract \
--administrator "${admin_pkh}" \
--output-address kt1_mutran_contract.txt
‖ [FA2->Info]:
‖ Originations:
‖ * Success: mutran_contract (The default with mutez transfer entry-point)
‖ -> KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
Команда сохранила адрес контракта в файле:
$ cat kt1_mutran_contract.txt
┃ KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
И, мы уже можем отображать состояние контракта (хранилища):
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)"
‖ [FA2->Info]:
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
‖ Balance: 0 mutez
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
‖ Status: Ready
‖ Tokens-big-map: 42
‖ Ledger-big-map: 40
‖ Operators-big-map: 41
‖ All-Tokens: None
‖ Known-Owners-and-Operators: None
Чтобы выпускать токены, администратор должен иметь возможность вызывать контракт в цепочке, для этого нам нужно передать как минимум несколько μꜩ на этот адрес. Можно использовать
tezos-client
, но у fatoo
есть команда быстрого доступа для перевода с настрое нной учетной записи «спонсора» (суммы указаны в mutez
): $ fatoo fund-address \
"${admin_pkh}" \
10_000_000
‖ [FA2->Info]: Balance for tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe is now
‖ 1019633807 mutez.
Обратите внимание, что на данный момент
owner0
не существует в цепочке, мы все еще выпускаем для них токены: $ fatoo call-mint --token-id 0 --token-symbol TQ0 \
"${owner0_pkh}" 1_000_000 \
--source "${admin_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
┃ (Pair (Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" 1000000) (Pair "TQ0" 0))
Давайте добавим еще один токен
TQ1
, который все еще выпускается для owner0
: $ fatoo call-mint --token-id 1 --token-symbol TQ1 \
"${owner0_pkh}" 2_000 \
--source "${admin_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
┃ (Pair (Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" 2000) (Pair "TQ1" 1))
Посмотрим на хранилище; мы видим новые токены
TQ0
и TQ1
, и, поскольку мы указываем «известного владельца токена» в командной строке, мы можем видеть их балансы: $ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
--known-address "$(cut -d, -f 3 owner0.csv)"
‖ [FA2->Info]:
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
‖ Balance: 0 mutez
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
‖ Status: Ready
‖ Tokens-big-map: 42
‖ Ledger-big-map: 40
‖ Operators-big-map: 41
‖ All-Tokens: 0 = TQ0.
‖ 1 = TQ1.
‖ Known-Owners-and-Operators:
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" [0 ops]
‖ - Balance: 1000000 TQ0(0)
‖ - Balance: 2000 TQ1(1)
Теперь давайте заставим
owner0
выполнить пакетную передачу. Во-первых, нам нужно подать немного горючего по этому адресу: $ fatoo fund-address \
"${owner0_pkh}" \
1_000_000
‖ [FA2->Info]: Balance for tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS is now 1704820
‖ mutez.
Затем, поскольку владелец токена может выполнять самопередачу, мы используем секретный ключ для
owner1
для передачи TQ0 и TQ1 owner1
и owner2
: $ fatoo call-transfer \
"from:${owner0_pkh} to:${owner1_pkh} amount: 10 token: 0" \
"from:${owner0_pkh} to:${owner1_pkh} amount: 100 token: 1" \
"from:${owner0_pkh} to:${owner2_pkh} amount: 10 token: 1" \
--source "${owner0_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
┃ { Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" { Pair "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" (Pair 0 10) ; Pair "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" (Pair 1 100) ; Pair "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V" (Pair 1 10)}}
Затем мы можем наблюдать получившееся состояние:
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
--known-address "$(cut -d, -f 3 owner0.csv)" \
--known-address "$(cut -d, -f 3 owner1.csv)" \
--known-address "$(cut -d, -f 3 owner2.csv)"
‖ [FA2->Info]:
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
‖ Balance: 0 mutez
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
‖ Status: Ready
‖ Tokens-big-map: 42
‖ Ledger-big-map: 40
‖ Operators-big-map: 41
‖ All-Tokens: 0 = TQ0.
‖ 1 = TQ1.
‖ Known-Owners-and-Operators:
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" [0 ops]
‖ - Balance: 999990 TQ0(0)
‖ - Balance: 1890 TQ1(1)
‖ * Owner: "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" [0 ops]
‖ - Balance: 10 TQ0(0)
‖ - Balance: 100 TQ1(1)
‖ * Owner: "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V" [0 ops]
‖ - Balance: 10 TQ1(1)
Давайте создадим пару ключей для
operator
: $ fatoo account-of-seed \
"youve-been-operated-ill-be-back" \
--output operator.csv
export operator_pkh="$(cut -d, -f 3 operator.csv)"
export operator_sk="$(cut -d, -f 4 operator.csv)"
Теперь мы заставим всех владельцев делегировать «оператору», см. Также команду
fatoo call-update-operators --help
: $ fatoo call-update-operators \
"[email protected] operator: ${operator_pkh} owner: ${owner0_pkh}" \
--source "${owner0_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
fatoo fund-address \
"${owner1_pkh}" \
1_000_000
fatoo call-update-operators \
"[email protected] operator: ${operator_pkh} owner: ${owner1_pkh}" \
--source "${owner1_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
fatoo fund-address \
"${owner2_pkh}" \
1_000_000
fatoo call-update-operators \
"[email protected] operator: ${operator_pkh} owner: ${owner2_pkh}" \
--source "${owner2_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
Мы видим, что теперь один и тот же оператор присутствует в каждой учетной записи:
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
--known-address "$(cut -d, -f 3 owner0.csv)" \
--known-address "$(cut -d, -f 3 owner1.csv)" \
--known-address "$(cut -d, -f 3 owner2.csv)" \
--known-address "$(cut -d, -f 3 operator.csv)"
‖ [FA2->Info]:
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
‖ Balance: 0 mutez
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
‖ Status: Ready
‖ Tokens-big-map: 42
‖ Ledger-big-map: 40
‖ Operators-big-map: 41
‖ All-Tokens: 0 = TQ0.
‖ 1 = TQ1.
‖ Known-Owners-and-Operators:
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS"
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
‖ - Balance: 999990 TQ0(0)
‖ - Balance: 1890 TQ1(1)
‖ * Owner: "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS"
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
‖ - Balance: 10 TQ0(0)
‖ - Balance: 100 TQ1(1)
‖ * Owner: "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V"
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
‖ - Balance: 10 TQ1(1)
‖ * Owner: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" [0 ops] [0 toks]
Наконец, давайте заставим
operator
запустить трансфер пакетного ограбления всех токенов: $ fatoo fund-address \
"${operator_pkh}" \
2_000_000_000
‖ [FA2->Info]: Balance for tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85 is now
‖ 2999839761 mutez.
$ fatoo call-transfer \
"from:${owner0_pkh} to:${operator_pkh} amount: 999990 token: 0" \
"from:${owner0_pkh} to:${operator_pkh} amount: 1890 token: 1" \
"from:${owner1_pkh} to:${operator_pkh} amount: 10 token: 0" \
"from:${owner1_pkh} to:${operator_pkh} amount: 100 token: 1" \
"from:${owner2_pkh} to:${operator_pkh} amount: 10 token: 1" \
--source "${operator_sk}" \
--address "$(cat kt1_mutran_contract.txt)"
┃ { Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" { Pair "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" (Pair 0 999990) ; Pair "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" (Pair 1 1890)} ; Pair "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" { Pair "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" (Pair 0 10) ; Pair "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" (Pair 1 100)} ; Pair "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V" { Pair "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" (Pair 1 10)}}
Затем мы можем наблюдать результирующее состояние, в котором все балансы равны
0
, за исключением operator
, которому принадлежат вообще все токены: $ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
--known-address "$(cut -d, -f 3 owner0.csv)" \
--known-address "$(cut -d, -f 3 owner1.csv)" \
--known-address "$(cut -d, -f 3 owner2.csv)" \
--known-address "$(cut -d, -f 3 operator.csv)"
‖ [FA2->Info]:
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
‖ Balance: 0 mutez