FA2-SmartPy
В этом руководстве показано, как взаимодействовать с «FA2-SmartPy» реализацией стандарта FA2 в некоторых распространенных сценариях использования. В первой части используются команды tezos-client для работы с основными передачами и запросами. Вторая часть идет дальше: она использует интерфейс командной строки fatoo для пакетной передачи и использует механизм «оператора» для делегирования прав передачи.

Базовое использование с tezos-client

Это предполагает, что у вас правильно настроен tezos-client для взаимодействия с Carthagenet или с «полной» песочницей.
Для этой части требуется 4 аккаунта, с несколькими импортироваными в tezos-client ꜩ . Аккаунты: administrator, originator, alice иbob.
Согласно нашему руководству по песочнице мы используем alice также как originator и administrator:
1
$ tezos-client import secret key alice \
2
unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq \
3
--force
4
tezos-client import secret key originator \
5
unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq \
6
--force
7
tezos-client import secret key administrator \
8
unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq \
9
--force
10
tezos-client import secret key bob \
11
unencrypted:edsk3RFfvaFaxbHx8BMtEW1rKQcPtDML3LXjNqMNLCzC3wLC1bWbAt \
12
--force
Copied!

Получение кода Майкельсона

FA2-SmartPy использует средства метапрограммирования SmartPy для предоставления более одного контракта Майкельсона. Такие контракты также известны как «сборки». Некоторые сборки доступны по адресу https://gitlab.com/smondet/fa2-smartpy/-/tree/master/michelson, далее в руководстве будет описание различных сборок.
Скачиваем сборку «по умолчанию»:
1
$ wget -O fa2_default.tz \
2
'https://gitlab.com/smondet/fa2-smartpy/-/raw/a58e9f11/michelson/20200724-170337+0000_8cee712_contract.tz'
Copied!

Создание

Создание работает так же, как и для любого контракта, нам нужен приведенный выше код, несколько ꜩ и выражение Майкельсона для инициализации хранилища. В нашем случае это должно выглядеть так:
1
(Pair
2
(Pair "<admin-pkh>" (Pair <nb-of-tokens> <ledger-big-map>))
3
(Pair (Pair Unit <operators-big-set>)
4
(Pair <paused> <tokens-big-map>)))
Copied!
Ожидается, что <nb-of-tokens> является кардиналом карты <tokens-big-map>, а в <ledger-big-map> используются только «известные» токены. Чтобы правильно поддерживать все инварианты, рекомендуется инициализировать хранилище пустым и использовать точку входа %mint для заполнения контракта.
Создадим такой не приостановленный пустой контракт при установке адреса administrator:
1
$ tezos-client originate contract myfa2 \
2
transferring 0 from originator \
3
running fa2_default.tz \
4
--init '(Pair (Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" (Pair 0 {})) (Pair (Pair Unit {}) (Pair False {})))' \
5
--burn-cap 10 \
6
--force --no-print-source
7
┃ Node is bootstrapped.
8
┃ Estimated gas: 130373 units (will add 100 for safety)
9
┃ Estimated storage: 4447 bytes added (will add 20 for safety)
10
┃ Operation successfully injected in the node.
11
┃ Operation hash is 'onosZKPHVN5dGy7LGKX2NV3Tyy3Dyg7qMNeGAn1Eqp7Mwx8sazk'
12
┃ Waiting for the operation to be included...
13
┃ Operation found in block: BM31KMRfkmiDDBMfaq9tCQe5TM6Xhxp3D8XseDWMynG7k81S9q8 (pass: 3, offset: 0)
14
15
...
16
17
┃ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.257
18
┃ New contract KT1Wf2sNVoosmXZqXEppsPZkS4BNAUL7hjTL originated.
19
┃ The operation has only been included 0 blocks ago.
20
┃ We recommend to wait more.
21
┃ Use command
22
┃ tezos-client wait for onosZKPHVN5dGy7LGKX2NV3Tyy3Dyg7qMNeGAn1Eqp7Mwx8sazk to be included --confirmations 30 --branch BMHcbMLmK3avi1ntw9rtcMgyPFjzyUxXhf5a8zDdjKM8eqJHenx
23
┃ and/or an external block explorer.
24
┃ Contract memorized as myfa2.
Copied!

Выпуск

Здесь мы хотим сделать перевод в качестве administrator, установленного в предыдущем разделе.
Точка входа для выпуска не имеет жесткой стандартизации в спецификации FA2, для fa2-smartpy она должна выглядеть так:
1
(Pair (Pair "<address>" <amount>) (Pair "<token-symbol>" <token-id>))
Copied!
Сборка по умолчанию предполагает, что идентификаторы токенов являются последовательными натуральными числами (0, 1, 2, ...), если из-за какого-то конкретного ограничения пользователю требуются произвольные идентификаторы токенов, в FA2-SmartPy есть опция сборки для создания такого контракта ( см. документацию).
Например, давайте, как administrator, выпустим 100 TK0 токенов на счет alice:
1
$ tezos-client transfer 0 from administrator to myfa2 \
2
--entrypoint mint \
3
--arg '(Pair (Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" 100) (Pair "TK0" 0))' \
4
--burn-cap 3
5
┃ Node is bootstrapped.
6
┃ Estimated gas: 113946 units (will add 100 for safety)
7
┃ Estimated storage: 163 bytes added (will add 20 for safety)
8
┃ Operation successfully injected in the node.
9
┃ Operation hash is 'onpcARPLVMjXqRfjFxyaZFGnpbCdsP2uSVKQwMiBHie4ujRf7fe'
10
┃ Waiting for the operation to be included...
11
┃ Operation found in block: BMCwBfn9B2E5zmrNfAu3z4rwoTo3h2DhDjTFgsn4BvTB21Xguff (pass: 3, offset: 0)
12
13
...
14
15
┃ Consumed gas: 113946
16
┃ Balance updates:
17
┃ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.163
18
┃ The operation has only been included 0 blocks ago.
19
┃ We recommend to wait more.
20
┃ Use command
21
┃ tezos-client wait for onpcARPLVMjXqRfjFxyaZFGnpbCdsP2uSVKQwMiBHie4ujRf7fe to be included --confirmations 30 --branch BM31KMRfkmiDDBMfaq9tCQe5TM6Xhxp3D8XseDWMynG7k81S9q8
22
┃ and/or an external block explorer.
Copied!

Перевод

Точка входа передачи в FA2 «группируется» на двух уровнях, т.е. один контрактный вызов содержит список элементов передачи, каждый элемент передачи является «адресом отправителя» и списком исходящих транзакций:
1
{
2
Pair "<from-1>" {Pair "<to-1>" (Pair <token-id-1> <amount-1>)} ;
3
Pair "<from-2>" {Pair "<to-2>" (Pair <token-id-2> <amount-2>) ; Pair "<to-3>" (Pair <token-id-3> <amount-3>)} ;
4
...
5
}
Copied!
Здесь мы, как alice, переводим 5 из наших 100 TK0 на аккаунт bob:
1
$ tezos-client transfer 0 from alice to myfa2 \
2
--entrypoint transfer \
3
--arg '{ Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" {Pair "tz1aSkwEot3L2kmUvcoxzjMomb9mvBNuzFK6" (Pair 0 5)} }' \
4
--burn-cap 3
5
┃ Node is bootstrapped.
6
┃ Estimated gas: 116015 units (will add 100 for safety)
7
┃ Estimated storage: 67 bytes added (will add 20 for safety)
8
┃ Operation successfully injected in the node.
9
┃ Operation hash is 'ontGCqsFh1uSDp5vmucU6EJxkivXw6bto2DN8LRekhXdo6WSTjK'
10
┃ Waiting for the operation to be included...
11
┃ Operation found in block: BLgT1CrszWaeEnxo4ncHWHwRZ1g39ig1NxT2zQB8AtCaFKhijnn (pass: 3, offset: 0)
12
┃ This sequence of operations was run:
13
14
...
15
16
┃ Consumed gas: 116015
17
┃ Balance updates:
18
┃ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.067
19
┃ The operation has only been included 0 blocks ago.
20
┃ We recommend to wait more.
21
┃ Use command
22
┃ tezos-client wait for ontGCqsFh1uSDp5vmucU6EJxkivXw6bto2DN8LRekhXdo6WSTjK to be included --confirmations 30 --branch BMCwBfn9B2E5zmrNfAu3z4rwoTo3h2DhDjTFgsn4BvTB21Xguff
23
┃ and/or an external block explorer.
Copied!

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

В качестве примера взаимодействия с big-картами в хранилище контрактов с помощью Michelson и tezos-client мы получаем баланс Алисы в токенах TK0.
Нам нужен скрипт, который принимает тип хранилища контракта в качестве параметра (буквально копирует и вставляет) и использует Майкельсон для извлечения значения в карту %ledger; в этом случае мы просто отображаем его с инструкцией FAILWITH, но можно было бы сделать гораздо больше, включая помещение в память (оставлено как упражнение для читателя ☺). Сохраним его как get-balance.tz:
1
parameter
2
(pair (pair (address %administrator)
3
(pair (nat %all_tokens) (big_map %ledger (pair address nat) nat)))
4
(pair (pair (unit %version_20200724_tzip_a57dfe86_contract)
5
(big_map %operators (pair (address %owner) (address %operator)) unit))
6
(pair (bool %paused)
7
(big_map %tokens
8
nat
9
(pair (nat %token_id)
10
(pair (string %symbol)
11
(pair (string %name) (pair (nat %decimals) (map %extras string string))))))))) ;
12
storage unit;
13
code
14
{
15
CAR ; # Get parameter
16
CAR ; # Get the pair (admin , _)
17
CDR ; # Get the pair (all_token, ledger)
18
CDR ; # Get %ledger
19
PUSH (pair address nat) (Pair "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" 0);
20
GET ; # Get the value in the ledger at the above key
21
FAILWITH
22
};
Copied!
В этом случае мы ожидаем сбоя команды tezos-client, поскольку мы хотим прочитать сообщение об ошибке:
1
$ tezos-client run script get-balance.tz on storage Unit \
2
and input \
3
"$(tezos-client get contract storage for myfa2)"
4
5
...
6
7
20: GET ; # Get the value in the ledger at the above key
8
21: FAILWITH
9
22: };
10
‖ At line 21 characters 4 to 12,
11
‖ script reached FAILWITH instruction
12
‖ with (Some 95)
13
‖ Fatal error:
14
‖ error running script
Copied!
Мы можем отчетливо видеть в значении ошибки (переданном в FAILWITH), что баланс aliceсоставляет 95 TK0 (100 выпущено минус 5 переведено в аккаунт bob).

Приложение fatoo

Получение и настройка клиента

В этом разделе мы используем интерфейс командной строки fatoo для некоторых сборок FA2-SmartPy. Вам нужно установить fatoo по вашему $PATH, или вы можете использовать Docker:
1
$ fatoo --version
2
# or:
3
docker run -it --rm --entrypoint fatoo registry.gitlab.com/smondet/fa2-smartpy:a58e9f11-run --version
Copied!
В приложении 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 следующим образом:
1
export fatoo_client='http://:20000/unencrypted:edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq?wait=0'
2
3
# Or, for docker, use:
4
5
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'
Copied!
В приложении есть подкоманда client, которая просто правильно вызывает tezos-client, их настройку можно проверить с помощью:
1
$ fatoo client bootstrapped
2
┃ Node is bootstrapped.
Copied!

Настройка аккаунтов

Здесь мы создаем четыре пары ключей из мнемонических семян, которые будут использоваться в следующих разделах:
1
$ fatoo account-of-seed \
2
"the-only-administrator-of-the-contract" \
3
--output admin.csv
4
fatoo account-of-seed \
5
"the-0th-aka-first-owner" \
6
--output owner0.csv
7
fatoo account-of-seed \
8
"ready-owner-one" \
9
--output owner1.csv
10
fatoo account-of-seed \
11
"this-is-a-potential-token-owner-too" \
12
--output owner2.csv
Copied!
Полученные CSV имеют тот же формат, что и flextesa, они содержат: <phrase>,<pk>,<pkh>,<sk>. См., например:
1
$ echo "Public key hash: $(cut -d, -f 3 admin.csv)"
2
echo "Secret key: $(cut -d, -f 4 admin.csv)"
3
┃ Public key hash: tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe
4
┃ Secret key: unencrypted:edsk3ZAm4BwNkG2uUmCcA64BadPWuwNt16zZisnfcQEuvyStaBa6oG
Copied!
Установим имена для всего этого:
1
$ export admin_pkh="$(cut -d, -f 3 admin.csv)"
2
export admin_sk="$(cut -d, -f 4 admin.csv)"
3
export owner0_pkh="$(cut -d, -f 3 owner0.csv)"
4
export owner0_sk="$(cut -d, -f 4 owner0.csv)"
5
export owner1_pkh="$(cut -d, -f 3 owner1.csv)"
6
export owner1_sk="$(cut -d, -f 4 owner1.csv)"
7
export owner2_pkh="$(cut -d, -f 3 owner2.csv)"
8
export owner2_sk="$(cut -d, -f 4 owner2.csv)"
Copied!

Создание

Приложение содержит код для нескольких вариантов контракта:
1
$ fatoo list-contract-variants \
2
--details description --format markdown
3
┃ * `contract`: The default.
4
┃ * `dbg_contract`: The default in debug mode.
5
┃ * `baby_contract`: The default in Babylon mode.
6
┃ * `nolay_contract`: The default without right-combs.
7
┃ * `mutran_contract`: The default with mutez transfer entry-point.
8
┃ * `tokset_contract`: The default with non-consecutive token-IDs.
9
┃ * `perdesc_noops_contract`: The default without operators and with permissions-descriptor.
10
┃ * `perdesc_noops_dbg_contract`: The perdesc_noops_contract but in debug mode.
11
┃ * `single_contract`: The default for single-asset.
12
┃ * `single_mutran_contract`: The single-asset with mutez transfer entry-point.
13
┃ * `nft_mutran_contract`: The default in NFT mode with mutez transfer entry-point.
14
┃ * `lzep_contract`: The default with lazy-entry-points flag.
15
┃ * `lzepm_contract`: The default with lazy-entry-points-multiple flag.
16
┃ * `lzep_mutran_contract`: The default with mutez-transfer and lazy-entry-points flag.
17
┃ * `lzepm_mutran_contract`: The default with mutez-transfer and lazy-entry-points-multiple flag.
Copied!
Можно сбросить код Майкельсона в файл (см. fatoo get-code --help), но в этом нет необходимости, поскольку можно напрямую создавать контракты из приложения. Давайте создадим mutran_contract, полномасштабную реализацию FA2 с дополнительной точкой входа, которая позволяет администратору переводить средства, которые потенциально могут оказаться на балансе контракта.
1
$ fatoo originate mutran_contract \
2
--administrator "${admin_pkh}" \
3
--output-address kt1_mutran_contract.txt
4
5
[FA2->Info]:
6
‖ Originations:
7
‖ * Success: mutran_contract (The default with mutez transfer entry-point)
8
‖ -> KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
Copied!
Команда сохранила адрес контракта в файле:
1
$ cat kt1_mutran_contract.txt
2
┃ KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
Copied!
И, мы уже можем отображать состояние контракта (хранилища):
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)"
2
[FA2->Info]:
3
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
4
‖ Balance: 0 mutez
5
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
6
‖ Status: Ready
7
‖ Tokens-big-map: 42
8
‖ Ledger-big-map: 40
9
‖ Operators-big-map: 41
10
‖ All-Tokens: None
11
‖ Known-Owners-and-Operators: None
Copied!

Выпуск и мультитрансфер

Чтобы выпускать токены, администратор должен иметь возможность вызывать контракт в цепочке, для этого нам нужно передать как минимум несколько μꜩ на этот адрес. Можно использовать tezos-client, но у fatoo есть команда быстрого доступа для перевода с настроенной учетной записи «спонсора» (суммы указаны в mutez):
1
$ fatoo fund-address \
2
"${admin_pkh}" \
3
10_000_000
4
[FA2->Info]: Balance for tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe is now
5
1019633807 mutez.
Copied!
Обратите внимание, что на данный момент owner0 не существует в цепочке, мы все еще выпускаем для них токены:
1
$ fatoo call-mint --token-id 0 --token-symbol TQ0 \
2
"${owner0_pkh}" 1_000_000 \
3
--source "${admin_sk}" \
4
--address "$(cat kt1_mutran_contract.txt)"
5
(Pair (Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" 1000000) (Pair "TQ0" 0))
Copied!
Давайте добавим еще один токен TQ1, который все еще выпускается для owner0:
1
$ fatoo call-mint --token-id 1 --token-symbol TQ1 \
2
"${owner0_pkh}" 2_000 \
3
--source "${admin_sk}" \
4
--address "$(cat kt1_mutran_contract.txt)"
5
(Pair (Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" 2000) (Pair "TQ1" 1))
Copied!
Посмотрим на хранилище; мы видим новые токены TQ0 и TQ1, и, поскольку мы указываем «известного владельца токена» в командной строке, мы можем видеть их балансы:
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
2
--known-address "$(cut -d, -f 3 owner0.csv)"
3
[FA2->Info]:
4
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
5
‖ Balance: 0 mutez
6
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
7
‖ Status: Ready
8
‖ Tokens-big-map: 42
9
‖ Ledger-big-map: 40
10
‖ Operators-big-map: 41
11
‖ All-Tokens: 0 = TQ0.
12
1 = TQ1.
13
‖ Known-Owners-and-Operators:
14
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" [0 ops]
15
‖ - Balance: 1000000 TQ0(0)
16
‖ - Balance: 2000 TQ1(1)
Copied!
Теперь давайте заставим owner0 выполнить пакетную передачу. Во-первых, нам нужно подать немного горючего по этому адресу:
1
$ fatoo fund-address \
2
"${owner0_pkh}" \
3
1_000_000
4
[FA2->Info]: Balance for tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS is now 1704820
5
‖ mutez.
Copied!
Затем, поскольку владелец токена может выполнять самопередачу, мы используем секретный ключ для owner1 для передачи TQ0 и TQ1 owner1 и owner2:
1
$ fatoo call-transfer \
2
"from:${owner0_pkh} to:${owner1_pkh} amount: 10 token: 0" \
3
"from:${owner0_pkh} to:${owner1_pkh} amount: 100 token: 1" \
4
"from:${owner0_pkh} to:${owner2_pkh} amount: 10 token: 1" \
5
--source "${owner0_sk}" \
6
--address "$(cat kt1_mutran_contract.txt)"
7
{ Pair "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" { Pair "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" (Pair 0 10) ; Pair "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" (Pair 1 100) ; Pair "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V" (Pair 1 10)}}
Copied!
Затем мы можем наблюдать получившееся состояние:
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
2
--known-address "$(cut -d, -f 3 owner0.csv)" \
3
--known-address "$(cut -d, -f 3 owner1.csv)" \
4
--known-address "$(cut -d, -f 3 owner2.csv)"
5
[FA2->Info]:
6
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
7
‖ Balance: 0 mutez
8
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
9
‖ Status: Ready
10
‖ Tokens-big-map: 42
11
‖ Ledger-big-map: 40
12
‖ Operators-big-map: 41
13
‖ All-Tokens: 0 = TQ0.
14
1 = TQ1.
15
‖ Known-Owners-and-Operators:
16
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS" [0 ops]
17
‖ - Balance: 999990 TQ0(0)
18
‖ - Balance: 1890 TQ1(1)
19
‖ * Owner: "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS" [0 ops]
20
‖ - Balance: 10 TQ0(0)
21
‖ - Balance: 100 TQ1(1)
22
‖ * Owner: "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V" [0 ops]
23
‖ - Balance: 10 TQ1(1)
Copied!

Использование операторов

Давайте создадим пару ключей для operator:
1
$ fatoo account-of-seed \
2
"youve-been-operated-ill-be-back" \
3
--output operator.csv
4
export operator_pkh="$(cut -d, -f 3 operator.csv)"
5
export operator_sk="$(cut -d, -f 4 operator.csv)"
Copied!
Теперь мы заставим всех владельцев делегировать «оператору», см. Также командуfatoo call-update-operators --help:
1
$ fatoo call-update-operators \
2
"[email protected] operator: ${operator_pkh} owner: ${owner0_pkh}" \
3
--source "${owner0_sk}" \
4
--address "$(cat kt1_mutran_contract.txt)"
5
fatoo fund-address \
6
"${owner1_pkh}" \
7
1_000_000
8
fatoo call-update-operators \
9
"[email protected] operator: ${operator_pkh} owner: ${owner1_pkh}" \
10
--source "${owner1_sk}" \
11
--address "$(cat kt1_mutran_contract.txt)"
12
fatoo fund-address \
13
"${owner2_pkh}" \
14
1_000_000
15
fatoo call-update-operators \
16
"[email protected] operator: ${operator_pkh} owner: ${owner2_pkh}" \
17
--source "${owner2_sk}" \
18
--address "$(cat kt1_mutran_contract.txt)"
Copied!
Мы видим, что теперь один и тот же оператор присутствует в каждой учетной записи:
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
2
--known-address "$(cut -d, -f 3 owner0.csv)" \
3
--known-address "$(cut -d, -f 3 owner1.csv)" \
4
--known-address "$(cut -d, -f 3 owner2.csv)" \
5
--known-address "$(cut -d, -f 3 operator.csv)"
6
[FA2->Info]:
7
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
8
‖ Balance: 0 mutez
9
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
10
‖ Status: Ready
11
‖ Tokens-big-map: 42
12
‖ Ledger-big-map: 40
13
‖ Operators-big-map: 41
14
‖ All-Tokens: 0 = TQ0.
15
1 = TQ1.
16
‖ Known-Owners-and-Operators:
17
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS"
18
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
19
‖ - Balance: 999990 TQ0(0)
20
‖ - Balance: 1890 TQ1(1)
21
‖ * Owner: "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS"
22
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
23
‖ - Balance: 10 TQ0(0)
24
‖ - Balance: 100 TQ1(1)
25
‖ * Owner: "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V"
26
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
27
‖ - Balance: 10 TQ1(1)
28
‖ * Owner: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" [0 ops] [0 toks]
Copied!
Наконец, давайте заставим operator запустить трансфер пакетного ограбления всех токенов:
1
$ fatoo fund-address \
2
"${operator_pkh}" \
3
2_000_000_000
4
5
[FA2->Info]: Balance for tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85 is now
6
2999839761 mutez.
Copied!
1
$ fatoo call-transfer \
2
"from:${owner0_pkh} to:${operator_pkh} amount: 999990 token: 0" \
3
"from:${owner0_pkh} to:${operator_pkh} amount: 1890 token: 1" \
4
"from:${owner1_pkh} to:${operator_pkh} amount: 10 token: 0" \
5
"from:${owner1_pkh} to:${operator_pkh} amount: 100 token: 1" \
6
"from:${owner2_pkh} to:${operator_pkh} amount: 10 token: 1" \
7
--source "${operator_sk}" \
8
--address "$(cat kt1_mutran_contract.txt)"
9
{ 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)}}
Copied!
Затем мы можем наблюдать результирующее состояние, в котором все балансы равны 0, за исключением operator, которому принадлежат вообще все токены:
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)" \
2
--known-address "$(cut -d, -f 3 owner0.csv)" \
3
--known-address "$(cut -d, -f 3 owner1.csv)" \
4
--known-address "$(cut -d, -f 3 owner2.csv)" \
5
--known-address "$(cut -d, -f 3 operator.csv)"
6
[FA2->Info]:
7
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
8
‖ Balance: 0 mutez
9
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
10
‖ Status: Ready
11
‖ Tokens-big-map: 42
12
‖ Ledger-big-map: 40
13
‖ Operators-big-map: 41
14
‖ All-Tokens: 0 = TQ0.
15
1 = TQ1.
16
‖ Known-Owners-and-Operators:
17
‖ * Owner: "tz1MUP3sCWTUQRG2Hon7uhRfmuYZ4guEQntS"
18
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
19
‖ - Balance: 0 TQ0(0)
20
‖ - Balance: 0 TQ1(1)
21
‖ * Owner: "tz1YYrxf529d3EYzEv5TnsiTpRCzFFB87dAS"
22
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
23
‖ - Balance: 0 TQ0(0)
24
‖ - Balance: 0 TQ1(1)
25
‖ * Owner: "tz1TyFYCuKrQ7A3yB4AvpoPRLacb3J6iQB9V"
26
‖ - Operator: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85"
27
‖ - Balance: 0 TQ1(1)
28
‖ * Owner: "tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85" [0 ops]
29
‖ - Balance: 1000000 TQ0(0)
30
‖ - Balance: 2000 TQ1(1)
Copied!

Получение баланса контракта

Сборка контракта, которую мы создали выше, имеет дополнительную точку входа, чтобы иметь возможность перенести баланс контракта, например на случай, если кто-то случайно переведет μꜩ на контракт.
Итак, давайте представим, что после вышеупомянутого ограбления operator хочет публично дать чаевые/подкупить администратора(ов) контракта, пройдя через сам контракт (это может быть запутанным предлогом для включения XTZ в контракт…). Мы вызываем точку входа transfer с пустым списком элементов передачи, но с несколькими XTZ в качестве суммы:
1
$ tezos-client import secret key operator \
2
"${operator_sk}" --force
3
tezos-client transfer 1_000 from operator \
4
to "$(cat kt1_mutran_contract.txt)" \
5
--entrypoint transfer \
6
--arg '{}' --burn-cap 1
7
8
...
9
10
┃ Balance updates:
11
┃ tz1NkpWhHsBSZHPg2Ljz2hycRiZvcYdcyu85 ... -ꜩ1000
12
┃ KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9 ... +ꜩ1000
13
┃ The operation has only been included 0 blocks ago.
14
┃ We recommend to wait more.
15
┃ Use command
16
┃ tezos-client wait for op2Cibz8jgB2Djb8MEqUg8X7mfKLzywo9SuQxxR2nDMVJZMH14N to be included --confirmations 30 --branch BMWfkKTCCWBatJ3rRXjp2H7DW3cwU4dr8cmP2ddccvnFi1z4geT
17
┃ and/or an external block explorer.
Copied!
Мы видим, что теперь fatoo показывает ненулевой баланс контракта:
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)"
2
[FA2->Info]:
3
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
4
‖ Balance: 1000000000 mutez
5
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
6
‖ Status: Ready
7
‖ Tokens-big-map: 42
8
‖ Ledger-big-map: 40
9
‖ Operators-big-map: 41
10
‖ All-Tokens: 0 = TQ0.
11
1 = TQ1.
12
‖ Known-Owners-and-Operators: None
Copied!
Давайте заставим admin забрать эти деньги себе; точка входа называется mutez_transfer и принимает пару mutez × address:
1
$ tezos-client import secret key admin \
2
"${admin_sk}" --force
3
tezos-client transfer 0 from admin \
4
to "$(cat kt1_mutran_contract.txt)" \
5
--entrypoint mutez_transfer \
6
--arg "Pair 1000000000 \"${admin_pkh}\"" \
7
--burn-cap 1
8
9
...
10
11
┃ Balance updates:
12
┃ KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9 ... -ꜩ1000
13
┃ tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe ... +ꜩ1000
14
┃ The operation has only been included 0 blocks ago.
15
┃ We recommend to wait more.
16
┃ Use command
17
┃ tezos-client wait for ooQZfBpcar3jevFxpbvUkdgZPJ67kSrtQ4DAaFDUpkoNAnrV7ji to be included --confirmations 30 --branch BLKDsTiAm4sdSGiKnTuiwmyaSo6NoaVgChPPab3voLoiuvwFfRV
18
┃ and/or an external block explorer.
Copied!
Мы видим, что баланс КТ1 обнулен:
1
$ fatoo show-storage "$(cat kt1_mutran_contract.txt)"
2
[FA2->Info]:
3
‖ Contract: KT1MSQj5BUmuuDMqoz4jpwabAcuxmhnUjhd9
4
‖ Balance: 0 mutez
5
‖ Administrator: "tz1ZnxqPNMXyiZLTANYJLJ9ZTBpQ5Qu16BXe"
6
‖ Status: Ready
7
‖ Tokens-big-map: 42
8
‖ Ledger-big-map: 40
9
‖ Operators-big-map: 41
10
‖ All-Tokens: 0 = TQ0.
11
1 = TQ1.
12
‖ Known-Owners-and-Operators: None
Copied!
... и увидим, что admin стал богаче:
1
$ tezos-client get balance for \
2
"${admin_pkh}"
3
2019.268775
4
‖ Warning: the --addr --port --tls options are now deprecated; use --endpoint instead
Copied!

Также читайте

Будем надеяться, в этом руководстве достаточно ясно представлена FA2-SmartPy реализация FA2 с точки зрения пользователя. Пожалуйста, поделитесь своим мнением, используя раздел проблемы репозитория. Дополнительные материалы для чтения:
Материалы разработаны TQ Tezos переведены на русский язык Tezos Ukraine
Last modified 1yr ago