Ton

Форк
0
/
nft-collection-editable.fc 
173 строки · 6.1 Кб
1
;; NFT collection smart contract
2

3
;; storage scheme
4
;; default#_ royalty_factor:uint16 royalty_base:uint16 royalty_address:MsgAddress = RoyaltyParams;
5
;; storage#_ owner_address:MsgAddress next_item_index:uint64
6
;;           ^[collection_content:^Cell common_content:^Cell]
7
;;           nft_item_code:^Cell
8
;;           royalty_params:^RoyaltyParams
9
;;           = Storage;
10

11
#include "op-codes.fc";
12
#include "stdlib.fc";
13
#include "params.fc";
14

15
(slice, int, cell, cell, cell) load_data() inline {
16
  var ds = get_data().begin_parse();
17
  return
18
    (ds~load_msg_addr(), ;; owner_address
19
     ds~load_uint(64), ;; next_item_index
20
     ds~load_ref(), ;; content
21
     ds~load_ref(), ;; nft_item_code
22
     ds~load_ref()  ;; royalty_params
23
     );
24
}
25

26
() save_data(slice owner_address, int next_item_index, cell content, cell nft_item_code, cell royalty_params) impure inline {
27
  set_data(begin_cell()
28
    .store_slice(owner_address)
29
    .store_uint(next_item_index, 64)
30
    .store_ref(content)
31
    .store_ref(nft_item_code)
32
    .store_ref(royalty_params)
33
    .end_cell());
34
}
35

36
cell calculate_nft_item_state_init(int item_index, cell nft_item_code) {
37
  cell data = begin_cell().store_uint(item_index, 64).store_slice(my_address()).end_cell();
38
  return begin_cell().store_uint(0, 2).store_dict(nft_item_code).store_dict(data).store_uint(0, 1).end_cell();
39
}
40

41
slice calculate_nft_item_address(int wc, cell state_init) {
42
  return begin_cell().store_uint(4, 3)
43
                     .store_int(wc, 8)
44
                     .store_uint(cell_hash(state_init), 256)
45
                     .end_cell()
46
                     .begin_parse();
47
}
48

49
() deploy_nft_item(int item_index, cell nft_item_code, int amount, cell nft_content) impure {
50
  cell state_init = calculate_nft_item_state_init(item_index, nft_item_code);
51
  slice nft_address = calculate_nft_item_address(workchain(), state_init);
52
  var msg = begin_cell()
53
            .store_uint(0x18, 6)
54
            .store_slice(nft_address)
55
            .store_coins(amount)
56
            .store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
57
            .store_ref(state_init)
58
            .store_ref(nft_content);
59
  send_raw_message(msg.end_cell(), 1); ;; pay transfer fees separately, revert on errors
60
}
61

62
() send_royalty_params(slice to_address, int query_id, slice data) impure inline {
63
  var msg = begin_cell()
64
    .store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool packages:MsgAddress -> 011000
65
    .store_slice(to_address)
66
    .store_coins(0)
67
    .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
68
    .store_uint(op::report_royalty_params(), 32)
69
    .store_uint(query_id, 64)
70
    .store_slice(data);
71
  send_raw_message(msg.end_cell(), 64); ;; carry all the remaining value of the inbound message
72
}
73

74
() recv_internal(cell in_msg_full, slice in_msg_body) impure {
75
    if (in_msg_body.slice_empty?()) { ;; ignore empty messages
76
        return ();
77
    }
78
    slice cs = in_msg_full.begin_parse();
79
    int flags = cs~load_uint(4);
80

81
    if (flags & 1) { ;; ignore all bounced messages
82
        return ();
83
    }
84
    slice sender_address = cs~load_msg_addr();
85

86
    int op = in_msg_body~load_uint(32);
87
    int query_id = in_msg_body~load_uint(64);
88

89
    var (owner_address, next_item_index, content, nft_item_code, royalty_params) = load_data();
90

91
    if (op == op::get_royalty_params()) {
92
        send_royalty_params(sender_address, query_id, royalty_params.begin_parse());
93
        return ();
94
    }
95

96
    throw_unless(401, equal_slices(sender_address, owner_address));
97

98

99
    if (op == 1) { ;; deploy new nft
100
      int item_index = in_msg_body~load_uint(64);
101
      throw_unless(402, item_index <= next_item_index);
102
      var is_last = item_index == next_item_index;
103
      deploy_nft_item(item_index, nft_item_code, in_msg_body~load_coins(), in_msg_body~load_ref());
104
      if (is_last) {
105
        next_item_index += 1;
106
        save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);
107
      }
108
      return ();
109
    }
110
    if (op == 2) { ;; batch deploy of new nfts
111
      int counter = 0;
112
      cell deploy_list = in_msg_body~load_ref();
113
      do {
114
        var (item_index, item, f?) = deploy_list~udict::delete_get_min(64);
115
        if (f?) {
116
          counter += 1;
117
          if (counter >= 250) { ;; Limit due to limits of action list size
118
            throw(399);
119
          }
120

121
          throw_unless(403 + counter, item_index <= next_item_index);
122
          deploy_nft_item(item_index, nft_item_code, item~load_coins(), item~load_ref());
123
          if (item_index == next_item_index) {
124
            next_item_index += 1;
125
          }
126
        }
127
      } until ( ~ f?);
128
      save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);
129
      return ();
130
    }
131
    if (op == 3) { ;; change owner
132
      slice new_owner = in_msg_body~load_msg_addr();
133
      save_data(new_owner, next_item_index, content, nft_item_code, royalty_params);
134
      return ();
135
    }
136
    if (op == 4) { ;; change content
137
      save_data(owner_address, next_item_index, in_msg_body~load_ref(), nft_item_code, in_msg_body~load_ref());
138
      return ();
139
    }
140
    throw(0xffff);
141
}
142

143
;; Get methods
144

145
(int, cell, slice) get_collection_data() method_id {
146
  var (owner_address, next_item_index, content, _, _) = load_data();
147
  slice cs = content.begin_parse();
148
  return (next_item_index, cs~load_ref(), owner_address);
149
}
150

151
slice get_nft_address_by_index(int index) method_id {
152
    var (_, _, _, nft_item_code, _) = load_data();
153
    cell state_init = calculate_nft_item_state_init(index, nft_item_code);
154
    return calculate_nft_item_address(0, state_init);
155
}
156

157
(int, int, slice) royalty_params() method_id {
158
     var (_, _, _, _, royalty) = load_data();
159
     slice rs = royalty.begin_parse();
160
     return (rs~load_uint(16), rs~load_uint(16), rs~load_msg_addr());
161
}
162

163
cell get_nft_content(int index, cell individual_nft_content) method_id {
164
  var (_, _, content, _, _) = load_data();
165
  slice cs = content.begin_parse();
166
  cs~load_ref();
167
  slice common_content = cs~load_ref().begin_parse();
168
  return (begin_cell()
169
                      .store_uint(1, 8) ;; offchain tag
170
                      .store_slice(common_content)
171
                      .store_ref(individual_nft_content)
172
          .end_cell());
173
}
174

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

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.