FA1.2 Lorentz
Создание контракта на базе стандарта токена FA1.2 Tezos блокчейна
Установите инструменты
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
:$ 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.
$ 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_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 [email protected];)"}
Обратите внимание, что здесь мы также устанавливаем
--burn-cap
заглушку.Определив функцию
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)
Если вы используете 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'
>>> 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()
Наконец, используя схему параметров, мы можем выполнить передачу, используя следующие шаги:
- Выпуск
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
является ключевым словом и не может использоваться для указания аргумента, поэтому мы используем **{..}
для преобразования словаря в аргументы ключевого слова.Эта ошибка возникает, когда зависимая операция еще не включена, и может принимать одну из следующих форм:
$ 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]`
Эта ошибка может возникнуть, если параметр
--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
)Last modified 2yr ago