x
807
1183
{ parameter (or
(or
(or
(or (address %addContract)
(pair %balance_of
(list %requests (pair (address %owner) (nat %token_id)))
(contract %callback (list (pair
(pair %request (address %owner)
(nat %token_id))
(nat %balance))))))
(or (pair %burn (nat %token_id) (address %from_))
(pair %mint (pair (address %to_) (nat %token_id))
(map %token_info string bytes))))
(or (or (address %removeContract) (bool %setBurnPause))
(or (bool %setContractPause) (bytes %setMetadata))))
(or
(or
(list %transfer (pair (address %from_)
(list %txs (pair (address %to_)
(pair (nat %token_id)
(nat %amount))))))
(pair %updateMetadataWithFunction
(lambda %metadata_updater (map string bytes) (map string bytes))
(nat %token_id)))
(or (address %updateMultisig)
(list %update_operators (or
(pair %add_operator (address %owner)
(pair
(address %operator)
(nat %token_id)))
(pair %remove_operator (address %owner)
(pair
(address %operator)
(nat %token_id)))))))) ;
storage (pair
(pair
(pair (pair (bool %burn_paused) (bool %contract_paused))
(pair (set %contracts address) (big_map %ledger nat address)))
(pair (pair (big_map %metadata string bytes) (address %multisig))
(pair (big_map %operators (pair address (pair address nat)) unit)
(big_map %token_metadata nat
(pair (nat %token_id)
(map %token_info string bytes))))))
(nat %total_supply)) ;
code { PUSH string "FA2_TOKEN_UNDEFINED" ;
PUSH string "FA2_INSUFFICIENT_BALANCE" ;
LAMBDA
(pair (pair address address)
(pair nat (big_map (pair address (pair address nat)) unit)))
unit
{ UNPAIR ;
UNPAIR ;
DIG 2 ;
UNPAIR ;
DUP 4 ;
DUP 4 ;
COMPARE ;
EQ ;
IF
{ DROP 4 ; UNIT }
{ DIG 3 ;
PAIR ;
DIG 2 ;
PAIR ;
MEM ;
IF { UNIT } { PUSH string "FA2_NOT_OPERATOR" ; FAILWITH } } } ;
DIG 3 ;
UNPAIR ;
IF_LEFT
{ DIG 3 ;
DROP ;
IF_LEFT
{ IF_LEFT
{ DIG 2 ;
DROP ;
IF_LEFT
{ DIG 2 ;
DROP ;
SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CAR ;
CDR ;
SENDER ;
COMPARE ;
NEQ ;
IF
{ SELF_ADDRESS ;
DIG 2 ;
DUP ;
CAR ;
CDR ;
CAR ;
CDR ;
CONTRACT %callMultisig (pair
(pair %entrypoint_signature
(string %name)
(pair (bytes %params)
(address %source_contract)))
(lambda %callback unit
(list operation))) ;
IF_NONE
{ SWAP ;
DIG 2 ;
DROP 2 ;
PUSH string "no call entrypoint" ;
FAILWITH }
{ SELF_ADDRESS ;
DUP 5 ;
PACK ;
SHA256 ;
PUSH string "addContract" ;
PAIR 3 ;
SWAP ;
PUSH mutez 0 ;
DIG 5 ;
DIG 5 ;
PAIR ;
LAMBDA
(pair (pair address address) unit)
(list operation)
{ CAR ;
UNPAIR ;
CONTRACT %addContract address ;
IF_NONE
{ DROP ;
PUSH string "no addContract entrypoint" ;
FAILWITH }
{ NIL operation ;
SWAP ;
PUSH mutez 0 ;
DIG 3 ;
TRANSFER_TOKENS ;
CONS } } ;
SWAP ;
APPLY ;
DIG 3 ;
PAIR ;
TRANSFER_TOKENS ;
NIL operation ;
SWAP ;
CONS } ;
PAIR }
{ SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
DUP 4 ;
CAR ;
CAR ;
CDR ;
CDR ;
DUP 5 ;
CAR ;
CAR ;
CDR ;
CAR ;
DIG 4 ;
PUSH bool True ;
SWAP ;
UPDATE ;
PAIR ;
DIG 3 ;
CAR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CDR ;
CDR ;
SWAP ;
DUP ;
CAR ;
MAP { DUP 3 ;
SWAP ;
DUP ;
DUG 2 ;
CDR ;
GET ;
IF_NONE
{ DROP ; DUP 4 ; FAILWITH }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
SWAP ;
COMPARE ;
EQ ;
IF { PUSH nat 1 } { PUSH nat 0 } ;
SWAP ;
PAIR } } ;
DIG 2 ;
DIG 4 ;
DROP 2 ;
SWAP ;
CDR ;
PUSH mutez 0 ;
DIG 2 ;
TRANSFER_TOKENS ;
SWAP ;
NIL operation ;
DIG 2 ;
CONS ;
PAIR } }
{ DIG 3 ;
DROP ;
IF_LEFT
{ PUSH bool True ;
DUP 3 ;
CAR ;
CAR ;
CAR ;
CAR ;
COMPARE ;
EQ ;
IF
{ DROP 3 ; PUSH string "Burn is paused" ; FAILWITH }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CDR ;
CAR ;
SENDER ;
MEM ;
NOT ;
IF
{ DROP 3 ;
PUSH string "Unauthorized contract address" ;
FAILWITH }
{ UNPAIR ;
DUP 3 ;
CAR ;
CAR ;
CDR ;
CDR ;
SWAP ;
DUP ;
DUG 2 ;
GET ;
IF_NONE
{ SWAP ;
DIG 3 ;
DROP 2 ;
PUSH string "Token id does not exist" ;
FAILWITH }
{ DIG 2 ;
SWAP ;
DUP ;
DUG 2 ;
COMPARE ;
NEQ ;
IF
{ DIG 3 ;
DROP 2 ;
PUSH string "Invalid owner address" ;
FAILWITH }
{ DUP 3 ;
CAR ;
CDR ;
CDR ;
CAR ;
DUP 3 ;
PAIR ;
SENDER ;
DIG 2 ;
PAIR ;
PAIR ;
DIG 3 ;
SWAP ;
EXEC ;
DROP ;
SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CDR ;
CDR ;
NONE address ;
DUP 3 ;
UPDATE } } ;
PUSH nat 1 ;
DUP 4 ;
CDR ;
SUB ;
ISNAT ;
IF_NONE { PUSH nat 0 } {} ;
DUP 4 ;
CDR ;
DUP 5 ;
CAR ;
CDR ;
DIG 3 ;
DUP 6 ;
CAR ;
CAR ;
CDR ;
CAR ;
PAIR ;
DUP 6 ;
CAR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
PAIR ;
DUP ;
CDR ;
DIG 4 ;
CAR ;
CDR ;
CDR ;
CDR ;
NONE (pair nat (map string bytes)) ;
DIG 5 ;
UPDATE ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
CAR ;
PAIR ;
DUP 3 ;
CAR ;
CDR ;
CAR ;
PAIR ;
DIG 2 ;
CAR ;
CAR ;
PAIR ;
PAIR ;
CAR ;
PAIR } } ;
NIL operation ;
PAIR }
{ DIG 2 ;
DROP ;
SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CAR ;
CDR ;
IF
{ DROP 2 ; PUSH string "Contract is paused" ; FAILWITH }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CDR ;
CAR ;
SENDER ;
MEM ;
NOT ;
IF
{ DROP 2 ;
PUSH string "Unauthorized contract address" ;
FAILWITH }
{ UNPAIR ;
UNPAIR ;
DUP 4 ;
CAR ;
CAR ;
CDR ;
CDR ;
DUP 3 ;
GET ;
IF_NONE
{}
{ DROP ; PUSH string "Token already exists" ; FAILWITH } ;
PUSH nat 1 ;
DUP 5 ;
CDR ;
ADD ;
DUP 5 ;
CDR ;
DUP 6 ;
CAR ;
CDR ;
DUP 7 ;
CAR ;
CAR ;
CDR ;
CDR ;
DIG 4 ;
SOME ;
DUP 6 ;
UPDATE ;
DUP 7 ;
CAR ;
CAR ;
CDR ;
CAR ;
PAIR ;
DUP 7 ;
CAR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
PAIR ;
DUP ;
CDR ;
DIG 5 ;
CAR ;
CDR ;
CDR ;
CDR ;
DIG 5 ;
DUP 6 ;
PAIR ;
SOME ;
DIG 5 ;
UPDATE ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
CAR ;
PAIR ;
DUP 3 ;
CAR ;
CDR ;
CAR ;
PAIR ;
DIG 2 ;
CAR ;
CAR ;
PAIR ;
PAIR ;
CAR ;
PAIR } } ;
NIL operation ;
PAIR } } }
{ DIG 2 ;
DIG 3 ;
DROP 2 ;
IF_LEFT
{ IF_LEFT
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CAR ;
CDR ;
SENDER ;
COMPARE ;
NEQ ;
IF
{ SELF_ADDRESS ;
DIG 2 ;
DUP ;
CAR ;
CDR ;
CAR ;
CDR ;
CONTRACT %callMultisig (pair
(pair %entrypoint_signature
(string %name)
(pair (bytes %params)
(address %source_contract)))
(lambda %callback unit
(list operation))) ;
IF_NONE
{ SWAP ;
DIG 2 ;
DROP 2 ;
PUSH string "no call entrypoint" ;
FAILWITH }
{ SELF_ADDRESS ;
DUP 5 ;
PACK ;
SHA256 ;
PUSH string "removeContract" ;
PAIR 3 ;
SWAP ;
PUSH mutez 0 ;
DIG 5 ;
DIG 5 ;
PAIR ;
LAMBDA
(pair (pair address address) unit)
(list operation)
{ CAR ;
UNPAIR ;
CONTRACT %removeContract address ;
IF_NONE
{ DROP ;
PUSH string "no removeContract entrypoint" ;
FAILWITH }
{ NIL operation ;
SWAP ;
PUSH mutez 0 ;
DIG 3 ;
TRANSFER_TOKENS ;
CONS } } ;
SWAP ;
APPLY ;
DIG 3 ;
PAIR ;
TRANSFER_TOKENS ;
NIL operation ;
SWAP ;
CONS } ;
PAIR }
{ SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
DUP 4 ;
CAR ;
CAR ;
CDR ;
CDR ;
DUP 5 ;
CAR ;
CAR ;
CDR ;
CAR ;
DIG 4 ;
PUSH bool False ;
SWAP ;
UPDATE ;
PAIR ;
DIG 3 ;
CAR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CAR ;
CDR ;
SENDER ;
COMPARE ;
NEQ ;
IF
{ SELF_ADDRESS ;
DIG 2 ;
DUP ;
CAR ;
CDR ;
CAR ;
CDR ;
CONTRACT %callMultisig (pair
(pair %entrypoint_signature
(string %name)
(pair (bytes %params)
(address %source_contract)))
(lambda %callback unit
(list operation))) ;
IF_NONE
{ SWAP ;
DIG 2 ;
DROP 2 ;
PUSH string "no call entrypoint" ;
FAILWITH }
{ SELF_ADDRESS ;
DUP 5 ;
PACK ;
SHA256 ;
PUSH string "setBurnPause" ;
PAIR 3 ;
SWAP ;
PUSH mutez 0 ;
DIG 5 ;
DIG 5 ;
PAIR ;
LAMBDA
(pair (pair address bool) unit)
(list operation)
{ CAR ;
UNPAIR ;
CONTRACT %setBurnPause bool ;
IF_NONE
{ DROP ;
PUSH string "no setBurnPause entrypoint" ;
FAILWITH }
{ NIL operation ;
SWAP ;
PUSH mutez 0 ;
DIG 3 ;
TRANSFER_TOKENS ;
CONS } } ;
SWAP ;
APPLY ;
DIG 3 ;
PAIR ;
TRANSFER_TOKENS ;
NIL operation ;
SWAP ;
CONS } ;
PAIR }
{ SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
DUP 4 ;
CAR ;
CAR ;
CDR ;
DIG 4 ;
CAR ;
CAR ;
CAR ;
CDR ;
DIG 4 ;
PAIR ;
PAIR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } } }
{ IF_LEFT
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CAR ;
CDR ;
SENDER ;
COMPARE ;
NEQ ;
IF
{ SELF_ADDRESS ;
DIG 2 ;
DUP ;
CAR ;
CDR ;
CAR ;
CDR ;
CONTRACT %callMultisig (pair
(pair %entrypoint_signature
(string %name)
(pair (bytes %params)
(address %source_contract)))
(lambda %callback unit
(list operation))) ;
IF_NONE
{ SWAP ;
DIG 2 ;
DROP 2 ;
PUSH string "no call entrypoint" ;
FAILWITH }
{ SELF_ADDRESS ;
DUP 5 ;
PACK ;
SHA256 ;
PUSH string "setContractPause" ;
PAIR 3 ;
SWAP ;
PUSH mutez 0 ;
DIG 5 ;
DIG 5 ;
PAIR ;
LAMBDA
(pair (pair address bool) unit)
(list operation)
{ CAR ;
UNPAIR ;
CONTRACT %setContractPause bool ;
IF_NONE
{ DROP ;
PUSH string "no setContractPause entrypoint" ;
FAILWITH }
{ NIL operation ;
SWAP ;
PUSH mutez 0 ;
DIG 3 ;
TRANSFER_TOKENS ;
CONS } } ;
SWAP ;
APPLY ;
DIG 3 ;
PAIR ;
TRANSFER_TOKENS ;
NIL operation ;
SWAP ;
CONS } ;
PAIR }
{ SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
DUP 4 ;
CAR ;
CAR ;
CDR ;
DIG 3 ;
DIG 4 ;
CAR ;
CAR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CAR ;
CDR ;
SENDER ;
COMPARE ;
NEQ ;
IF
{ SELF_ADDRESS ;
DIG 2 ;
DUP ;
CAR ;
CDR ;
CAR ;
CDR ;
CONTRACT %callMultisig (pair
(pair %entrypoint_signature
(string %name)
(pair (bytes %params)
(address %source_contract)))
(lambda %callback unit
(list operation))) ;
IF_NONE
{ SWAP ;
DIG 2 ;
DROP 2 ;
PUSH string "no call entrypoint" ;
FAILWITH }
{ SELF_ADDRESS ;
DUP 5 ;
PACK ;
SHA256 ;
PUSH string "setMetadata" ;
PAIR 3 ;
SWAP ;
PUSH mutez 0 ;
DIG 5 ;
DIG 5 ;
PAIR ;
LAMBDA
(pair (pair address bytes) unit)
(list operation)
{ CAR ;
UNPAIR ;
CONTRACT %setMetadata bytes ;
IF_NONE
{ DROP ;
PUSH string "no setMetadata entrypoint" ;
FAILWITH }
{ NIL operation ;
SWAP ;
PUSH mutez 0 ;
DIG 3 ;
TRANSFER_TOKENS ;
CONS } } ;
SWAP ;
APPLY ;
DIG 3 ;
PAIR ;
TRANSFER_TOKENS ;
NIL operation ;
SWAP ;
CONS } ;
PAIR }
{ SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
DUP 4 ;
CAR ;
CDR ;
CAR ;
CDR ;
DUP 5 ;
CAR ;
CDR ;
CAR ;
CAR ;
DIG 4 ;
SOME ;
PUSH string "content" ;
UPDATE ;
PAIR ;
PAIR ;
DIG 2 ;
CAR ;
CAR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } } } } }
{ IF_LEFT
{ IF_LEFT
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CAR ;
CDR ;
IF
{ DROP 5 ; PUSH string "Contract is paused" ; FAILWITH }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CAR ;
CDR ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
CAR ;
PAIR ;
DIG 3 ;
DUG 2 ;
UNPAIR ;
SWAP ;
DIG 2 ;
ITER { DUP ;
DUG 2 ;
CDR ;
ITER { SWAP ;
PUSH nat 0 ;
DUP 3 ;
GET 4 ;
COMPARE ;
EQ ;
IF
{ SWAP ; DROP }
{ PUSH nat 1 ;
DUP 3 ;
GET 4 ;
COMPARE ;
NEQ ;
IF
{ DROP 2 ; DUP 5 ; FAILWITH }
{ DUP ;
DUP 3 ;
GET 3 ;
GET ;
IF_NONE
{ DROP 2 ; DUP 6 ; FAILWITH }
{ DUP 4 ;
CAR ;
SWAP ;
DUP ;
DUG 2 ;
COMPARE ;
NEQ ;
IF
{ DROP 3 ; DUP 5 ; FAILWITH }
{ DUP 5 ;
DUP 4 ;
GET 3 ;
PAIR ;
SENDER ;
DIG 2 ;
PAIR ;
PAIR ;
DUP 6 ;
SWAP ;
EXEC ;
DROP ;
SWAP ;
DUP ;
DUG 2 ;
CAR ;
SOME ;
DIG 2 ;
GET 3 ;
UPDATE } } } } } ;
SWAP ;
DROP } ;
SWAP ;
DIG 2 ;
DIG 4 ;
DIG 5 ;
DROP 4 ;
SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
DIG 2 ;
DUP 4 ;
CAR ;
CAR ;
CDR ;
CAR ;
PAIR ;
DIG 3 ;
CAR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } }
{ DIG 2 ;
DIG 3 ;
DIG 4 ;
DROP 3 ;
UNPAIR ;
DUP 3 ;
CAR ;
CAR ;
CDR ;
CAR ;
SENDER ;
MEM ;
NOT ;
IF
{ DROP 3 ; PUSH string "Unauthorized contract address" ; FAILWITH }
{ DUP 3 ;
CAR ;
CDR ;
CDR ;
CDR ;
DUP 3 ;
GET ;
IF_NONE
{ DROP 3 ;
PUSH string "Token metadata does not exists" ;
FAILWITH }
{ CDR ;
EXEC ;
SWAP ;
DUP ;
DUG 2 ;
PAIR ;
DUP 3 ;
CDR ;
DUP 4 ;
CAR ;
CDR ;
CDR ;
CDR ;
DIG 2 ;
SOME ;
DIG 3 ;
UPDATE ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
CAR ;
PAIR ;
DUP 3 ;
CAR ;
CDR ;
CAR ;
PAIR ;
DIG 2 ;
CAR ;
CAR ;
PAIR ;
PAIR } } ;
NIL operation ;
PAIR } }
{ DIG 2 ;
DIG 3 ;
DIG 4 ;
DROP 3 ;
IF_LEFT
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CAR ;
CDR ;
SENDER ;
COMPARE ;
NEQ ;
IF
{ SELF_ADDRESS ;
DIG 2 ;
DUP ;
CAR ;
CDR ;
CAR ;
CDR ;
CONTRACT %callMultisig (pair
(pair %entrypoint_signature
(string %name)
(pair (bytes %params)
(address %source_contract)))
(lambda %callback unit
(list operation))) ;
IF_NONE
{ SWAP ; DIG 2 ; DROP 2 ; PUSH string "no call entrypoint" ; FAILWITH }
{ SELF_ADDRESS ;
DUP 5 ;
PACK ;
SHA256 ;
PUSH string "updateMultisig" ;
PAIR 3 ;
SWAP ;
PUSH mutez 0 ;
DIG 5 ;
DIG 5 ;
PAIR ;
LAMBDA
(pair (pair address address) unit)
(list operation)
{ CAR ;
UNPAIR ;
CONTRACT %updateMultisig address ;
IF_NONE
{ DROP ;
PUSH string "no updateMultisig entrypoint" ;
FAILWITH }
{ NIL operation ;
SWAP ;
PUSH mutez 0 ;
DIG 3 ;
TRANSFER_TOKENS ;
CONS } } ;
SWAP ;
APPLY ;
DIG 3 ;
PAIR ;
TRANSFER_TOKENS ;
NIL operation ;
SWAP ;
CONS } ;
PAIR }
{ SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
DIG 2 ;
DUP 4 ;
CAR ;
CDR ;
CAR ;
CAR ;
PAIR ;
PAIR ;
DIG 2 ;
CAR ;
CAR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } }
{ SWAP ;
DUP ;
DUG 2 ;
CAR ;
CDR ;
CDR ;
CAR ;
SWAP ;
SENDER ;
DUG 2 ;
ITER { SWAP ;
DUP 3 ;
DUP 3 ;
IF_LEFT {} {} ;
CAR ;
COMPARE ;
EQ ;
IF {} { PUSH string "FA2_NOT_OWNER" ; FAILWITH } ;
SWAP ;
IF_LEFT
{ SWAP ;
UNIT ;
SOME ;
DUP 3 ;
GET 4 ;
DUP 4 ;
GET 3 ;
PAIR ;
DIG 3 ;
CAR ;
PAIR ;
UPDATE }
{ DUP ;
DUG 2 ;
GET 4 ;
DUP 3 ;
GET 3 ;
PAIR ;
DIG 2 ;
CAR ;
PAIR ;
NONE unit ;
SWAP ;
UPDATE } } ;
SWAP ;
DROP ;
SWAP ;
DUP ;
DUG 2 ;
CDR ;
DUP 3 ;
CAR ;
CDR ;
CDR ;
CDR ;
DIG 2 ;
PAIR ;
DUP 3 ;
CAR ;
CDR ;
CAR ;
PAIR ;
DIG 2 ;
CAR ;
CAR ;
PAIR ;
PAIR ;
NIL operation ;
PAIR } } } } ;
view "total_supply_view" unit nat { CDR ; CDR } ;
view "balance_of_view" (pair (address %owner) (nat %token_id)) nat
{ UNPAIR ;
SWAP ;
CAR ;
CAR ;
CDR ;
CDR ;
SWAP ;
DUP ;
DUG 2 ;
CDR ;
GET ;
IF_NONE
{ DROP ; PUSH string "FA2_TOKEN_UNDEFINED" ; FAILWITH }
{ SWAP ; CAR ; SWAP ; COMPARE ; EQ ; IF { PUSH nat 1 } { PUSH nat 0 } } } }