Skip to content

Commit ce0ce19

Browse files
authored
refactor(benches): optimize NFT send (#3278)
1 parent 6d4dccb commit ce0ce19

File tree

4 files changed

+102
-57
lines changed

4 files changed

+102
-57
lines changed

src/benchmarks/nft/results_code_size.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,16 @@
189189
"item cells": "10",
190190
"item bits": "5393"
191191
}
192+
},
193+
{
194+
"label": "1.6.11 with optimized send",
195+
"pr": null,
196+
"size": {
197+
"collection cells": "39",
198+
"collection bits": "19604",
199+
"item cells": "10",
200+
"item bits": "5217"
201+
}
192202
}
193203
]
194204
}

src/benchmarks/nft/results_gas.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,16 @@
179179
"deploy nft": "10520",
180180
"batch deploy nft": "654138"
181181
}
182+
},
183+
{
184+
"label": "1.6.11 with optimized send",
185+
"pr": null,
186+
"gas": {
187+
"transfer": "6979",
188+
"get static data": "4424",
189+
"deploy nft": "10335",
190+
"batch deploy nft": "654266"
191+
}
182192
}
183193
]
184194
}

src/benchmarks/nft/tact/collection.tact

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,6 @@ import "./constants";
22
import "./messages";
33
import "./item";
44

5-
struct DictGet {
6-
itemIndex: Int? as uint64; // IndexSizeBits = 64
7-
item: Slice?;
8-
flag: Int;
9-
}
10-
11-
struct DictItem {
12-
amount: Int as coins;
13-
initNFTBody: Cell;
14-
}
15-
16-
// (int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
17-
asm(-> 1 0 2) fun dictGetMin(dict: Cell, keySize: Int): DictGet { DICTUMIN NULLSWAPIFNOT2 }
18-
19-
// (int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
20-
asm(-> 1 0 2) fun dictGetNext(pivot: Int, dict: Cell, keySize: Int): DictGet { DICTUGETNEXT NULLSWAPIFNOT2 }
21-
225
contract NFTCollection {
236
owner: Address;
247
nextItemIndex: Int as uint64; // IndexSizeBits = 64
@@ -42,6 +25,17 @@ contract NFTCollection {
4225

4326
receive() {} // ignore empty messages
4427

28+
receive(msg: DeployNFT) {
29+
throwUnless(IncorrectSender, sender() == self.owner);
30+
throwUnless(IncorrectIndex, msg.itemIndex <= self.nextItemIndex);
31+
32+
deployNFTItem(self.commonCode, msg.itemIndex, msg.amount, msg.initNFTBody, self.commonData);
33+
34+
if (msg.itemIndex == self.nextItemIndex) {
35+
self.nextItemIndex += 1;
36+
}
37+
}
38+
4539
receive(msg: GetRoyaltyParams) {
4640
message(MessageParameters {
4741
bounce: false,
@@ -55,17 +49,6 @@ contract NFTCollection {
5549
});
5650
}
5751

58-
receive(msg: DeployNFT) {
59-
throwUnless(IncorrectSender, sender() == self.owner);
60-
throwUnless(IncorrectIndex, msg.itemIndex <= self.nextItemIndex);
61-
62-
deployNFTItem(self.commonCode, msg.itemIndex, msg.amount, msg.initNFTBody, self.commonData);
63-
64-
if (msg.itemIndex == self.nextItemIndex) {
65-
self.nextItemIndex += 1;
66-
}
67-
}
68-
6952
receive(msg: BatchDeploy) {
7053
throwUnless(IncorrectSender, sender() == self.owner);
7154

@@ -136,3 +119,20 @@ inline fun deployNFTItem(commonCode: Cell, itemIndex: Int, amount: Int, initNFTB
136119
mode: SendPayFwdFeesSeparately,
137120
});
138121
}
122+
123+
struct DictGet {
124+
itemIndex: Int? as uint64; // IndexSizeBits = 64
125+
item: Slice?;
126+
flag: Int;
127+
}
128+
129+
struct DictItem {
130+
amount: Int as coins;
131+
initNFTBody: Cell;
132+
}
133+
134+
// (int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
135+
asm(-> 1 0 2) fun dictGetMin(dict: Cell, keySize: Int): DictGet { DICTUMIN NULLSWAPIFNOT2 }
136+
137+
// (int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
138+
asm(-> 1 0 2) fun dictGetNext(pivot: Int, dict: Cell, keySize: Int): DictGet { DICTUGETNEXT NULLSWAPIFNOT2 }

src/benchmarks/nft/tact/item.tact

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,6 @@
11
import "./constants";
22
import "./messages";
33

4-
inline fun sendMsg(toAddress: Address, amount: Int, op: Int, queryId: Int, payload: Builder, sendMode: Int) {
5-
let msgBody = beginCell().storeUint(op, 32).storeUint(queryId, 64);
6-
7-
if (payload.bits() != 0) {
8-
msgBody = msgBody.storeBuilder(payload);
9-
}
10-
11-
message(MessageParameters {
12-
bounce: false,
13-
to: toAddress,
14-
value: amount,
15-
body: msgBody.endCell(),
16-
mode: sendMode,
17-
});
18-
}
19-
204
struct NFTItemInit {
215
owner: Address;
226
content: Cell;
@@ -28,7 +12,22 @@ contract NFTItem(
2812
collectionAddress: Address,
2913
itemIndex: Int as uint64,
3014
) {
31-
receive() {} //to ignore empty messages
15+
receive() {} // ignore empty messages
16+
17+
receive(msg: GetStaticData) {
18+
throwUnless(NotInit, self.owner != null);
19+
20+
sendMsg(
21+
sender(),
22+
0,
23+
ReportStaticData,
24+
msg.queryId,
25+
beginCell()
26+
.storeUint(self.itemIndex, 256)
27+
.storeAddress(self.collectionAddress),
28+
SendRemainingValue,
29+
); // implementation detail
30+
}
3231

3332
receive(msg: Slice) {
3433
// Check if owner == null, which means the contract hasn't been initialized yet
@@ -52,35 +51,47 @@ contract NFTItem(
5251
throwUnless(IncorrectForwardPayload, msg.forwardPayload.bits() >= 1);
5352
forceBasechain(msg.newOwner);
5453

55-
let fwdFees: Int = context().readForwardFee();
54+
let fwdFees = context().readForwardFee();
5655

57-
let restAmount: Int = myBalance() - minTonsForStorage;
56+
let restAmount = myBalance() - minTonsForStorage;
5857
if (msg.forwardAmount > 0) {
59-
restAmount -= (msg.forwardAmount + fwdFees);
58+
restAmount -= msg.forwardAmount + fwdFees;
6059
}
6160

6261
// when we load addr_none$00 in tact we got null
63-
let needResponse: Bool = (msg.responseDestination != null);
62+
let needResponse = msg.responseDestination != null;
6463
if (needResponse) {
6564
restAmount -= fwdFees;
6665
}
6766

6867
throwUnless(InvalidFees, restAmount >= 0);
6968

7069
if (msg.forwardAmount > 0) {
71-
sendMsg(msg.newOwner, msg.forwardAmount, OwnershipAssigned, msg.queryId, beginCell().storeAddress(self.owner!!).storeSlice(msg.forwardPayload), SendPayFwdFeesSeparately);
70+
sendMsg(
71+
msg.newOwner,
72+
msg.forwardAmount,
73+
OwnershipAssigned,
74+
msg.queryId,
75+
beginCell()
76+
.storeAddress(self.owner!!)
77+
.storeSlice(msg.forwardPayload),
78+
SendPayFwdFeesSeparately,
79+
);
7280
}
81+
7382
if (needResponse) {
7483
forceBasechain(msg.responseDestination!!);
75-
sendMsg(msg.responseDestination!!, restAmount, Excesses, msg.queryId, beginCell(), SendPayFwdFeesSeparately);
84+
sendMsg(
85+
msg.responseDestination!!,
86+
restAmount,
87+
Excesses,
88+
msg.queryId,
89+
beginCell(),
90+
SendPayFwdFeesSeparately,
91+
);
7692
}
77-
self.owner = msg.newOwner;
78-
}
79-
80-
receive(msg: GetStaticData) {
81-
throwUnless(NotInit, self.owner != null);
8293

83-
sendMsg(sender(), 0, ReportStaticData, msg.queryId, beginCell().storeUint(self.itemIndex, 256).storeAddress(self.collectionAddress), SendRemainingValue); // implementation detail
94+
self.owner = msg.newOwner;
8495
}
8596

8697
get fun get_nft_data(): NFTData {
@@ -93,3 +104,17 @@ contract NFTItem(
93104
};
94105
}
95106
}
107+
108+
inline fun sendMsg(toAddress: Address, amount: Int, op: Int, queryId: Int, payload: Builder, sendMode: Int) {
109+
message(MessageParameters {
110+
bounce: false,
111+
to: toAddress,
112+
value: amount,
113+
body: beginCell()
114+
.storeUint(op, 32)
115+
.storeUint(queryId, 64)
116+
.storeBuilder(payload)
117+
.endCell(),
118+
mode: sendMode,
119+
});
120+
}

0 commit comments

Comments
 (0)