@layerzerolabs/layerzero-v2-ton 3.0.18-ton.2 → 3.0.19-ton.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/CHANGELOG.md +4 -88
  2. package/build/AllStorages.compiled.json +1 -1
  3. package/build/AllStorages.test.compiled.json +1 -1
  4. package/build/BaseContract.test.compiled.json +1 -1
  5. package/build/Channel.compiled.json +1 -1
  6. package/build/Channel.permissions.test.compiled.json +1 -1
  7. package/build/ChannelBurn.test.compiled.json +1 -1
  8. package/build/ChannelCommitPacket.test.compiled.json +1 -1
  9. package/build/ChannelConfig.test.compiled.json +1 -1
  10. package/build/ChannelInitialize.test.compiled.json +1 -1
  11. package/build/ChannelMsglibIntegration.test.compiled.json +1 -1
  12. package/build/ChannelMsglibSendCallback.test.compiled.json +1 -1
  13. package/build/ChannelNilify.test.compiled.json +1 -1
  14. package/build/ChannelReceive.test.compiled.json +1 -1
  15. package/build/ChannelReceiveCallback.test.compiled.json +1 -1
  16. package/build/ChannelReceiveView.test.compiled.json +1 -1
  17. package/build/ChannelSend.test.compiled.json +1 -1
  18. package/build/Classlib.test.compiled.json +1 -1
  19. package/build/ComputeDataSizeGas.test.compiled.json +1 -1
  20. package/build/Connection.compiled.json +1 -1
  21. package/build/Controller.assertions.test.compiled.json +1 -1
  22. package/build/Controller.compiled.json +1 -1
  23. package/build/Controller.permissions.test.compiled.json +1 -1
  24. package/build/Controller.test.compiled.json +1 -1
  25. package/build/Counter.compiled.json +1 -1
  26. package/build/Counter.permissions.test.compiled.json +1 -1
  27. package/build/Counter.setters.test.compiled.json +1 -1
  28. package/build/Counter.test.compiled.json +1 -1
  29. package/build/Dvn.compiled.json +1 -1
  30. package/build/Dvn.test.compiled.json +1 -1
  31. package/build/DvnFeeLib.compiled.json +1 -1
  32. package/build/DvnPermissions.test.compiled.json +1 -1
  33. package/build/Endpoint.compiled.json +1 -1
  34. package/build/Endpoint.permissions.test.compiled.json +1 -1
  35. package/build/Endpoint.test.compiled.json +1 -1
  36. package/build/EndpointSetEpConfigDefaults.test.compiled.json +1 -1
  37. package/build/Executor.compiled.json +1 -1
  38. package/build/Executor.test.compiled.json +1 -1
  39. package/build/ExecutorFeeLib.compiled.json +1 -1
  40. package/build/ExecutorPermissions.test.compiled.json +1 -1
  41. package/build/LzClasses.test.compiled.json +1 -1
  42. package/build/LzUtil.test.compiled.json +1 -1
  43. package/build/MsgData.test.compiled.json +1 -1
  44. package/build/MsglibPacketCodec.test.compiled.json +1 -1
  45. package/build/PipelinedOutOfOrder.test.compiled.json +1 -1
  46. package/build/PriceFeedCache.compiled.json +1 -1
  47. package/build/PriceFeedCache.permissions.test.compiled.json +1 -1
  48. package/build/PriceFeedCache.test.compiled.json +1 -1
  49. package/build/Proxy.compiled.json +1 -1
  50. package/build/Proxy.permissions.test.compiled.json +1 -1
  51. package/build/Proxy.test.compiled.json +1 -1
  52. package/build/SmlConnection.compiled.json +1 -1
  53. package/build/SmlConnection.permissions.test.compiled.json +1 -1
  54. package/build/SmlConnection.test.compiled.json +1 -1
  55. package/build/SmlManager.compiled.json +1 -1
  56. package/build/SmlManager.permissions.test.compiled.json +1 -1
  57. package/build/SmlManager.test.compiled.json +1 -1
  58. package/build/Uln.compiled.json +1 -1
  59. package/build/Uln.test.compiled.json +1 -1
  60. package/build/UlnConnection.compiled.json +1 -1
  61. package/build/UlnConnection.test.compiled.json +1 -1
  62. package/build/UlnConnectionPermissions.test.compiled.json +1 -1
  63. package/build/UlnManagement.test.compiled.json +1 -1
  64. package/build/UlnManager.compiled.json +1 -1
  65. package/build/UlnManager.test.compiled.json +1 -1
  66. package/build/UlnManagerPermissions.test.compiled.json +1 -1
  67. package/build/UlnManagerUtil.test.compiled.json +1 -1
  68. package/build/UlnPermissions.test.compiled.json +1 -1
  69. package/build/UlnReceiveConfig.test.compiled.json +1 -1
  70. package/build/UlnSend.test.compiled.json +1 -1
  71. package/build/UlnSendConfig.test.compiled.json +1 -1
  72. package/build/UlnSendWithDvnFeeLib.test.compiled.json +1 -1
  73. package/build/UlnSendWithExecFeeLib.test.compiled.json +1 -1
  74. package/build/UlnSendWorkerFactory.test.compiled.json +1 -1
  75. package/build/UlnUtil.test.compiled.json +1 -1
  76. package/build/WorkerCore.test.compiled.json +1 -1
  77. package/build/badFeeLib1.test.compiled.json +1 -1
  78. package/build/badFeeLib10.test.compiled.json +1 -1
  79. package/build/badFeeLib11.test.compiled.json +1 -1
  80. package/build/badFeeLib12.test.compiled.json +1 -0
  81. package/build/badFeeLib2.test.compiled.json +1 -1
  82. package/build/badFeeLib3.test.compiled.json +1 -1
  83. package/build/badFeeLib4.test.compiled.json +1 -1
  84. package/build/badFeeLib5.test.compiled.json +1 -1
  85. package/build/badFeeLib6.test.compiled.json +1 -1
  86. package/build/badFeeLib7.test.compiled.json +1 -1
  87. package/build/badFeeLib8.test.compiled.json +1 -1
  88. package/build/badFeeLib9.test.compiled.json +1 -1
  89. package/package.json +9 -6
  90. package/src/classes/lz/ReceiveEpConfig.fc +1 -1
  91. package/src/classes/msgdata/LzReceiveStatus.fc +0 -1
  92. package/src/funC++/actions/call.fc +1 -0
  93. package/src/funC++/actions/deploy.fc +0 -1
  94. package/src/funC++/actions/destroy.fc +0 -1
  95. package/src/funC++/actions/dispatch.fc +0 -1
  96. package/src/funC++/actions/event.fc +0 -1
  97. package/src/funC++/actions/payment.fc +0 -1
  98. package/src/funC++/actions/sendJettons.fc +0 -1
  99. package/src/funC++/actions/utils.fc +0 -2
  100. package/src/funC++/baseInterface.fc +0 -2
  101. package/src/funC++/classlib.fc +6 -81
  102. package/src/funC++/contractMain.fc +2 -8
  103. package/src/funC++/dataStructures/DeterministicInsertionCircularQueue.fc +0 -1
  104. package/src/funC++/dataStructures/PipelinedOutOfOrder.fc +0 -1
  105. package/src/funC++/handlerCore.fc +2 -6
  106. package/src/funC++/stringlib.fc +0 -2
  107. package/src/funC++/testutils.fc +0 -1
  108. package/src/funC++/txnContext.fc +1 -1
  109. package/src/funC++/utils.fc +35 -0
  110. package/src/protocol/channel/callbackOpcodes.fc +10 -0
  111. package/src/protocol/channel/handler.fc +1032 -0
  112. package/src/protocol/channel/interface.fc +60 -0
  113. package/src/protocol/channel/main.fc +39 -0
  114. package/src/protocol/channel/storage.fc +55 -0
  115. package/src/protocol/controller/handler.fc +347 -0
  116. package/src/protocol/controller/interface.fc +25 -0
  117. package/src/protocol/controller/main.fc +29 -0
  118. package/src/protocol/controller/storage.fc +31 -0
  119. package/src/protocol/core/abstract/protocolHandler.fc +110 -0
  120. package/src/protocol/core/abstract/protocolMain.fc +30 -0
  121. package/src/protocol/core/baseStorage.fc +33 -0
  122. package/src/protocol/endpoint/handler.fc +426 -0
  123. package/src/protocol/endpoint/interface.fc +20 -0
  124. package/src/protocol/endpoint/main.fc +23 -0
  125. package/src/protocol/endpoint/storage.fc +37 -0
  126. package/src/protocol/interfaces.fc +4 -0
  127. package/src/protocol/msglibs/BytesDecoder.fc +135 -0
  128. package/src/protocol/msglibs/BytesEncoder.fc +150 -0
  129. package/src/protocol/msglibs/interface.fc +16 -0
  130. package/src/protocol/msglibs/simpleMsglib/smlConnection/handler.fc +125 -0
  131. package/src/protocol/msglibs/simpleMsglib/smlConnection/interface.fc +3 -0
  132. package/src/protocol/msglibs/simpleMsglib/smlConnection/main.fc +19 -0
  133. package/src/protocol/msglibs/simpleMsglib/smlConnection/storage.fc +20 -0
  134. package/src/protocol/msglibs/simpleMsglib/smlManager/handler.fc +281 -0
  135. package/src/protocol/msglibs/simpleMsglib/smlManager/interface.fc +14 -0
  136. package/src/protocol/msglibs/simpleMsglib/smlManager/main.fc +24 -0
  137. package/src/protocol/msglibs/simpleMsglib/smlManager/storage.fc +38 -0
  138. package/src/protocol/msglibs/ultralightnode/callbackOpcodes.fc +1 -0
  139. package/src/protocol/msglibs/ultralightnode/feeLibInterface.fc +10 -0
  140. package/src/protocol/msglibs/ultralightnode/feeLibUtils.fc +51 -0
  141. package/src/protocol/msglibs/ultralightnode/msgdata/Attestation.fc +49 -0
  142. package/src/protocol/msglibs/ultralightnode/msgdata/DvnFeesPaidEvent.fc +26 -0
  143. package/src/protocol/msglibs/ultralightnode/msgdata/ExecutorFeePaidEvent.fc +23 -0
  144. package/src/protocol/msglibs/ultralightnode/msgdata/InitUln.fc +18 -0
  145. package/src/protocol/msglibs/ultralightnode/msgdata/InitUlnConnection.fc +62 -0
  146. package/src/protocol/msglibs/ultralightnode/msgdata/InitUlnManager.fc +18 -0
  147. package/src/protocol/msglibs/ultralightnode/msgdata/RentRefill.fc +18 -0
  148. package/src/protocol/msglibs/ultralightnode/msgdata/SetAdminWorkerAddresses.fc +18 -0
  149. package/src/protocol/msglibs/ultralightnode/msgdata/TreasuryFeeBps.fc +16 -0
  150. package/src/protocol/msglibs/ultralightnode/msgdata/UlnEvents.fc +26 -0
  151. package/src/protocol/msglibs/ultralightnode/msgdata/UlnReceiveConfig.fc +249 -0
  152. package/src/protocol/msglibs/ultralightnode/msgdata/UlnSend.fc +27 -0
  153. package/src/protocol/msglibs/ultralightnode/msgdata/UlnSendConfig.fc +170 -0
  154. package/src/protocol/msglibs/ultralightnode/msgdata/UlnVerification.fc +21 -0
  155. package/src/protocol/msglibs/ultralightnode/msgdata/UlnWorkerFeelibBytecode.fc +16 -0
  156. package/src/protocol/msglibs/ultralightnode/msgdata/UlnWorkerFeelibEvents.fc +58 -0
  157. package/src/protocol/msglibs/ultralightnode/msgdata/UlnWorkerFeelibInfo.fc +56 -0
  158. package/src/protocol/msglibs/ultralightnode/msgdata/VerificationStatus.fc +18 -0
  159. package/src/protocol/msglibs/ultralightnode/uln/handler.fc +803 -0
  160. package/src/protocol/msglibs/ultralightnode/uln/interface.fc +63 -0
  161. package/src/protocol/msglibs/ultralightnode/uln/main.fc +37 -0
  162. package/src/protocol/msglibs/ultralightnode/uln/storage.fc +43 -0
  163. package/src/protocol/msglibs/ultralightnode/ulnConnection/handler.fc +600 -0
  164. package/src/protocol/msglibs/ultralightnode/ulnConnection/interface.fc +36 -0
  165. package/src/protocol/msglibs/ultralightnode/ulnConnection/main.fc +32 -0
  166. package/src/protocol/msglibs/ultralightnode/ulnConnection/storage.fc +49 -0
  167. package/src/protocol/msglibs/ultralightnode/ulnConnection/utils.fc +141 -0
  168. package/src/protocol/msglibs/ultralightnode/ulnManager/handler.fc +495 -0
  169. package/src/protocol/msglibs/ultralightnode/ulnManager/interface.fc +59 -0
  170. package/src/protocol/msglibs/ultralightnode/ulnManager/main.fc +40 -0
  171. package/src/protocol/msglibs/ultralightnode/ulnManager/storage.fc +44 -0
  172. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/common.fc +27 -0
  173. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/dvnFeeLib/handler.fc +80 -0
  174. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/dvnFeeLib/main.fc +4 -0
  175. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/dvnFeeLib/storage.fc +26 -0
  176. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/executorFeeLib/handler.fc +123 -0
  177. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/executorFeeLib/main.fc +4 -0
  178. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/executorFeeLib/storage.fc +29 -0
  179. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/main.fc +3 -0
  180. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/priceFeedFeeLib/main.fc +1 -0
  181. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/priceFeedFeeLib/storage.fc +39 -0
  182. package/src/protocol/msglibs/ultralightnode/workerFeeLibs/ulnSendWorkerV1.fc +363 -0
  183. package/src/workers/core/abstract/workerHandler.fc +150 -0
  184. package/src/workers/core/interface.fc +25 -0
  185. package/src/workers/core/workerCoreStorage.fc +44 -0
  186. package/src/workers/dvn/handler.fc +332 -0
  187. package/src/workers/dvn/interface.fc +25 -0
  188. package/src/workers/dvn/main.fc +36 -0
  189. package/src/workers/dvn/storage.fc +27 -0
  190. package/src/workers/executor/handler.fc +110 -0
  191. package/src/workers/executor/interface.fc +19 -0
  192. package/src/workers/executor/main.fc +26 -0
  193. package/src/workers/executor/storage.fc +19 -0
  194. package/src/workers/msgdata/ExecuteParams.fc +29 -0
  195. package/src/workers/msgdata/NativeDrop.fc +16 -0
  196. package/src/workers/msgdata/ProxyMessage.fc +20 -0
  197. package/src/workers/msgdata/SetDict.fc +20 -0
  198. package/src/workers/msgdata/SetQuorum.fc +20 -0
  199. package/src/workers/msgdata/SignedRequest.fc +18 -0
  200. package/src/workers/priceFeedCache/handler.fc +114 -0
  201. package/src/workers/priceFeedCache/interface.fc +4 -0
  202. package/src/workers/priceFeedCache/main.fc +25 -0
  203. package/src/workers/priceFeedCache/storage.fc +21 -0
  204. package/src/workers/proxy/handler.fc +81 -0
  205. package/src/workers/proxy/interface.fc +11 -0
  206. package/src/workers/proxy/main.fc +17 -0
  207. package/src/workers/proxy/storage.fc +21 -0
  208. package/tests/testMain.fc +0 -1
@@ -0,0 +1,803 @@
1
+ #include "../../BytesEncoder.fc";
2
+
3
+ #include "../feeLibInterface.fc";
4
+ #include "../feeLibUtils.fc";
5
+
6
+ #include "../msgdata/DvnFeesPaidEvent.fc";
7
+ #include "../msgdata/ExecutorFeePaidEvent.fc";
8
+ #include "../msgdata/InitUln.fc";
9
+ #include "../msgdata/RentRefill.fc";
10
+ #include "../msgdata/TreasuryFeeBps.fc";
11
+ #include "../msgdata/UlnEvents.fc";
12
+ #include "../msgdata/UlnSend.fc";
13
+ #include "../msgdata/UlnSendConfig.fc";
14
+ #include "../msgdata/UlnWorkerFeelibEvents.fc";
15
+ #include "../msgdata/UlnWorkerFeelibInfo.fc";
16
+
17
+ #include "../ulnConnection/interface.fc";
18
+ #include "../ulnManager/interface.fc";
19
+
20
+ #include "../../../interfaces.fc";
21
+ #include "../../../channel/interface.fc";
22
+ #include "../../../core/abstract/protocolHandler.fc";
23
+
24
+ #include "../../../../classes/lz/Packet.fc";
25
+ #include "../../../../classes/msgdata/ExtendedMd.fc";
26
+ #include "../../../../classes/msgdata/LzSend.fc";
27
+ #include "../../../../classes/msgdata/MdAddress.fc";
28
+ #include "../../../../classes/msgdata/MdObj.fc";
29
+ #include "../../../../classes/msgdata/MsglibSendCallback.fc";
30
+ #include "../../../../classes/msgdata/SetAddress.fc";
31
+
32
+ #include "interface.fc";
33
+ #include "storage.fc";
34
+
35
+ const int _quoteWorkersMethodId = 23432;
36
+ ;;; ================INTERFACE FUNCTIONS=====================
37
+
38
+ (cell, tuple) _initialize(cell $initUln) impure inline {
39
+ (cell $storage, tuple actions) = preamble();
40
+
41
+ $storage = $storage
42
+ .cl::set(
43
+ Uln::connectionCode,
44
+ $initUln.cl::get<cellRef>(md::InitUln::connectionCode)
45
+ )
46
+ .cl::set(
47
+ Uln::treasuryFeeBps,
48
+ $initUln.cl::get<uint16>(md::InitUln::treasuryFeeBps)
49
+ )
50
+ .cl::set(
51
+ Uln::remainingWorkerSlots,
52
+ Uln::MaxWorkerFeelibs - UlnManager::CONST::MAX_ADMIN_WORKERS
53
+ )
54
+ .cl::set(
55
+ Uln::remainingAdminWorkerSlots,
56
+ UlnManager::CONST::MAX_ADMIN_WORKERS
57
+ );
58
+
59
+ return ($storage, actions);
60
+ }
61
+
62
+ int _getEventSink() impure {
63
+ return getOwner();
64
+ }
65
+
66
+ () assertConnection(cell $ulnSendMd) impure inline {
67
+ cell connectionCode = getContractStorage().cl::get<cellRef>(Uln::connectionCode);
68
+
69
+ cell $connectionInitialStorage = $ulnSendMd
70
+ .cl::get<objRef>(md::UlnSend::connectionInitialStorage);
71
+
72
+ int providedUlnManagerAddress = $connectionInitialStorage
73
+ .cl::get<objRef>(BASE_STORAGE_INDEX)
74
+ .cl::get<address>(BaseStorage::owner);
75
+
76
+ ;; By construction, if the bytecode is valid and the uln manager address is correct,
77
+ ;; then the uln address cannot be incorrect (assuming no bug in the ULN connection bytecode).
78
+ throw_unless(
79
+ Uln::ERROR::notUlnConnection,
80
+ (providedUlnManagerAddress == getOwner())
81
+ & (computeContractAddress($connectionInitialStorage, connectionCode) == getCaller())
82
+ );
83
+ }
84
+
85
+ cell _failedMsglibSendCallback(cell $lzSend) impure inline {
86
+ return md::MsglibSendCallback::New(
87
+ 0,
88
+ 0,
89
+ $lzSend,
90
+ empty_cell(),
91
+ empty_cell(),
92
+ 0,
93
+ 0,
94
+ 0,
95
+ 0,
96
+ cl::nullObject(),
97
+ Uln::ErrorCode::WORKER_QUOTE_FAILED
98
+ );
99
+ }
100
+
101
+ cell _quote(cell $ulnSendMd, cell $storage) impure inline {
102
+ cell $lzSend = $ulnSendMd.cl::get<objRef>(md::UlnSend::lzSend);
103
+
104
+ int ownerAddress = $storage
105
+ .cl::get<objRef>(BASE_STORAGE_INDEX)
106
+ .cl::get<address>(BaseStorage::owner);
107
+
108
+ (
109
+ int quoteGasLimit,
110
+ int maxMsgBytes,
111
+ int executor,
112
+ cell requiredDVNs,
113
+ cell optionalDVNs,
114
+ int confirmations,
115
+ int isValid
116
+ ) = lz::UlnSendConfig::resolveUlnSendConfig(
117
+ $ulnSendMd.cl::get<objRef>(md::UlnSend::customUlnSendConfig),
118
+ $storage.cl::get<objRef>(Uln::defaultUlnSendConfig)
119
+ );
120
+
121
+ ifnot (isValid) {
122
+ return md::MdAddress::New(
123
+ _failedMsglibSendCallback($lzSend),
124
+ ownerAddress
125
+ );
126
+ }
127
+
128
+ int messageBytes = lz::Packet::_messageBytes($lzSend.cl::get<objRef>(md::LzSend::packet));
129
+
130
+ tuple returnStack = unsafeTuple([null()]);
131
+
132
+ if (messageBytes <= maxMsgBytes) {
133
+ returnStack = safePackedInputsRunVm(
134
+ unsafeTuple([
135
+ $storage,
136
+ $lzSend,
137
+ executor,
138
+ requiredDVNs,
139
+ optionalDVNs,
140
+ confirmations,
141
+ messageBytes,
142
+ $lzSend.cl::get<objRef>(md::LzSend::extraOptions),
143
+ $lzSend.cl::get<objRef>(md::LzSend::enforcedOptions)
144
+ ]),
145
+ _quoteWorkersMethodId,
146
+ 1,
147
+ my_code().begin_parse(),
148
+ quoteGasLimit
149
+ );
150
+ }
151
+
152
+ cell $msglibSendCallback = returnStack.cell_at(0);
153
+ ifnot ($msglibSendCallback.is_cell()) {
154
+ return md::MdAddress::New(
155
+ _failedMsglibSendCallback($lzSend),
156
+ ownerAddress
157
+ );
158
+ }
159
+
160
+ return md::MdAddress::New(
161
+ $msglibSendCallback,
162
+ ownerAddress
163
+ );
164
+ }
165
+
166
+ ;; caller is responsible for asserting the worker exists
167
+ cell _removeWorker(cell $storage, cell $workerFeelibInfo) impure inline {
168
+ int workerAddress = $workerFeelibInfo.cl::get<address>(UlnWorkerFeelibInfo::workerAddress);
169
+ int workerSlotField = $workerFeelibInfo.cl::get<bool>(UlnWorkerFeelibInfo::isAdmin)
170
+ ? Uln::remainingAdminWorkerSlots
171
+ : Uln::remainingWorkerSlots;
172
+ return $storage
173
+ .cl::nestedDict256::delete(Uln::workerFeelibInfos, workerAddress)
174
+ .cl::set( workerSlotField, $storage.cl::get<uint16>(workerSlotField) + 1);
175
+ }
176
+
177
+ (int, cell) _quoteWorker(
178
+ cell $storage,
179
+ int workerAddress,
180
+ cell $path,
181
+ int confirmations,
182
+ int packetBytes,
183
+ cell $extraOptions,
184
+ cell $enforcedOptions
185
+ ) impure inline_ref method_id {
186
+ (cell $workerInfo, int workerExists) = $storage.cl::nestedDict256::get<cellRef>(
187
+ Uln::workerFeelibInfos,
188
+ workerAddress
189
+ );
190
+ ifnot (workerExists) {
191
+ return (-1, null());
192
+ }
193
+
194
+ (cell $friendInfo, int friendExists) = ($workerInfo, workerExists);
195
+ int friendWorkerAddress = $workerInfo
196
+ .cl::get<address>(UlnWorkerFeelibInfo::friendWorkerAddress);
197
+
198
+ ifnot (friendWorkerAddress == NULLADDRESS) {
199
+ ($friendInfo, friendExists) = $storage.cl::nestedDict256::get<cellRef>(
200
+ Uln::workerFeelibInfos,
201
+ friendWorkerAddress
202
+ );
203
+ }
204
+ ifnot (friendExists) {
205
+ return (-1, null());
206
+ }
207
+
208
+ tuple returnStack = safePackedInputsRunVm(
209
+ unsafeTuple(
210
+ [
211
+ $workerInfo.cl::get<objRef>(UlnWorkerFeelibInfo::workerFeelibStorage),
212
+ $friendInfo,
213
+ $path,
214
+ confirmations,
215
+ packetBytes,
216
+ $extraOptions,
217
+ $enforcedOptions
218
+ ]
219
+ ),
220
+ UlnWorkerInterface::quote,
221
+ 1,
222
+ $workerInfo.cl::get<cellRef>(UlnWorkerFeelibInfo::workerFeelibBytecode).begin_parse(),
223
+ MAX_U32 ;; gas limit doesn't matter for the inner call
224
+ );
225
+
226
+ tuple retVal = returnStack.tuple_at(0);
227
+ ;; if it's not a tuple, then the worker returned an error or went OOG
228
+ ifnot (retVal.is_tuple()) {
229
+ return (-1, null());
230
+ }
231
+
232
+ ;; the tuple must have exactly two items
233
+ ifnot (retVal.tlen() == 2) {
234
+ return (-1, null());
235
+ }
236
+
237
+ ;; the first item must be an int
238
+ int fee = retVal.int_at(0);
239
+ ifnot (fee.is_int()) {
240
+ return (-1, null());
241
+ }
242
+
243
+ ;; the second item must be a cell or null
244
+ cell event = retVal.cell_at(1);
245
+ ifnot ((event.is_cell()) | (event.is_null())) {
246
+ return (-1, null());
247
+ }
248
+
249
+ return (fee, event);
250
+ }
251
+
252
+ ;; return null on failure, actions on success
253
+ ;; tuple _quoteWorkers(cell $lzSend, int executor, cell requiredDVNs, cell optionalDVNs) impure inline {
254
+ cell _quoteWorkers(tuple args) impure inline method_id(23432) {
255
+ cell $storage = args.cell_at(0);
256
+ cell $lzSend = args.cell_at(1);
257
+ int executor = args.int_at(2);
258
+ cell requiredDVNsCell = args.cell_at(3);
259
+ cell optionalDVNsCell = args.cell_at(4);
260
+ int confirmations = args.int_at(5);
261
+ int packetBytes = args.int_at(6);
262
+ cell $extraOptions = args.cell_at(7);
263
+ cell $enforcedOptions = args.cell_at(8);
264
+ ;; quote the executor first
265
+ int totalNativeFee = 0;
266
+
267
+ slice requiredDVNs = requiredDVNsCell.begin_parse();
268
+ slice optionalDVNs = optionalDVNsCell.begin_parse();
269
+
270
+ cell $packet = $lzSend.cl::get<objRef>(md::LzSend::packet);
271
+ cell $path = $packet.cl::get<cellRef>(lz::Packet::path);
272
+
273
+ tuple payeesInfo = empty_tuple();
274
+ tuple workerEvents = UlnWorkerFeelibEventsBuilder::create();
275
+
276
+ while (requiredDVNs.slice_empty?() == false) {
277
+ int requiredDVNAddress = requiredDVNs~AddressList::next();
278
+ (int nativeFee, cell eventBody) = _quoteWorker(
279
+ $storage,
280
+ requiredDVNAddress,
281
+ $path,
282
+ confirmations,
283
+ packetBytes,
284
+ $extraOptions,
285
+ $enforcedOptions
286
+ );
287
+
288
+ if (nativeFee < 0) {
289
+ return null();
290
+ }
291
+
292
+ totalNativeFee += nativeFee;
293
+ payeesInfo = payeesInfo.tpush(unsafeTuple([requiredDVNAddress, nativeFee]));
294
+ workerEvents = workerEvents
295
+ .UlnWorkerFeelibEventsBuilder::push(requiredDVNAddress, eventBody);
296
+ }
297
+
298
+ while (optionalDVNs.slice_empty?() == false) {
299
+ int optionalDVNAddress = optionalDVNs~AddressList::next();
300
+ (int nativeFee, cell eventBody) = _quoteWorker(
301
+ $storage,
302
+ optionalDVNAddress,
303
+ $path,
304
+ confirmations,
305
+ packetBytes,
306
+ $extraOptions,
307
+ $enforcedOptions
308
+ );
309
+
310
+ if (nativeFee < 0) {
311
+ return null();
312
+ }
313
+
314
+ payeesInfo = payeesInfo.tpush(unsafeTuple([optionalDVNAddress, nativeFee]));
315
+ totalNativeFee += nativeFee;
316
+
317
+ workerEvents = workerEvents
318
+ .UlnWorkerFeelibEventsBuilder::push(optionalDVNAddress, eventBody);
319
+ }
320
+
321
+ ;; create the dvnPaidEvent
322
+ cell $dvnsFeesPaidEvent = DvnFeesPaidEvent::New(
323
+ requiredDVNsCell,
324
+ optionalDVNsCell,
325
+ serializePayees(payeesInfo)
326
+ );
327
+
328
+ (int executorFee, cell eventBody) = _quoteWorker(
329
+ $storage,
330
+ executor,
331
+ $path,
332
+ confirmations,
333
+ packetBytes,
334
+ $extraOptions,
335
+ $enforcedOptions
336
+ );
337
+
338
+ if (executorFee < 0) {
339
+ return null();
340
+ }
341
+
342
+ ;; add the executor fee
343
+ payeesInfo = payeesInfo.tpush(unsafeTuple([executor, executorFee]));
344
+ totalNativeFee += executorFee;
345
+
346
+ ;; add events from executor to workerEvents
347
+ workerEvents = workerEvents
348
+ .UlnWorkerFeelibEventsBuilder::push(executor, eventBody);
349
+
350
+ ;; create the executorPaidEvent
351
+ cell $executorFeePaidEvent = ExecutorFeePaidEvent::New(executor, executorFee);
352
+
353
+ ;; Handle treasury fee
354
+ int treasuryFee = totalNativeFee * $storage.cl::get<uint16>(Uln::treasuryFeeBps) / 10000;
355
+ payeesInfo = payeesInfo.tpush(
356
+ unsafeTuple([
357
+ $storage.cl::get<objRef>(BASE_STORAGE_INDEX).cl::get<address>(BaseStorage::owner),
358
+ treasuryFee
359
+ ])
360
+ );
361
+
362
+ cell ret = md::MsglibSendCallback::New(
363
+ totalNativeFee + treasuryFee,
364
+ 0,
365
+ $lzSend,
366
+ BytesEncoder::build<PacketV1>($packet).BytesEncoder::serialize(),
367
+ serializePayees(payeesInfo),
368
+ PacketV1::nonceOffsetBytes,
369
+ PacketV1::nonceBytes,
370
+ PacketV1::guidOffsetBytes,
371
+ PacketV1::guidBytes,
372
+ UlnEvents::New(
373
+ UlnWorkerFeelibEvents::FromBuilder(workerEvents),
374
+ $dvnsFeesPaidEvent,
375
+ $executorFeePaidEvent
376
+ ),
377
+ Channel::NO_ERROR
378
+ );
379
+ return ret;
380
+ }
381
+
382
+ ;;; ================PERMISSION FUNCTIONS=====================
383
+
384
+ () _checkPermissions(int op, cell $md) impure inline {
385
+ if (op == Uln::OP::ULN_SEND) {
386
+ return assertConnection($md);
387
+ } elseif (
388
+ (op == Uln::OP::ULN_VERIFY)
389
+ | (op == Uln::OP::ULN_COMMIT_PACKET)
390
+ ) {
391
+ return ();
392
+ } elseif (
393
+ (op == Uln::OP::DEREGISTER_WORKER_FEELIB)
394
+ | (op == Uln::OP::COLLECT_WORKER_RENT)
395
+ | (op == Uln::OP::SET_WORKER_FEELIB_STORAGE)
396
+ | (op == Uln::OP::REFILL_WORKER_RENT)
397
+ | (op == Uln::OP::GC_ATTESTATIONS)
398
+ ) {
399
+ return ();
400
+ } elseif (
401
+ (op == Uln::OP::SET_DEFAULT_ULN_RECEIVE_CONFIG)
402
+ | (op == Uln::OP::SET_DEFAULT_ULN_SEND_CONFIG)
403
+ | (op == Uln::OP::UPDATE_WORKER_FEELIB)
404
+ | (op == Uln::OP::SET_TREASURY_FEE_BPS)
405
+ ) {
406
+ return assertOwner();
407
+ } else {
408
+ ;; we must put a check for all opcodes to make sure we don't
409
+ ;; mistakenly miss an opp code's permissions
410
+ throw(BaseInterface::ERROR::invalidOpcode);
411
+ }
412
+ }
413
+
414
+ ;;; ==========================HANDLERS=====================================
415
+
416
+ tuple ulnQuote(cell $ulnSendMd) impure inline method_id {
417
+ (cell $storage, tuple actions) = preamble();
418
+
419
+ actions~pushAction<call>(
420
+ $ulnSendMd.cl::get<address>(md::UlnSend::forwardingAddress),
421
+ Msglib::OP::RETURN_QUOTE,
422
+ _quote($ulnSendMd, $storage)
423
+ );
424
+
425
+ return actions;
426
+ }
427
+
428
+ tuple ulnSend(cell $ulnSendMd) impure inline method_id {
429
+ (cell $storage, tuple actions) = preamble();
430
+
431
+ actions~pushAction<call>(
432
+ $ulnSendMd.cl::get<address>(md::UlnSend::forwardingAddress),
433
+ Channel::OP::MSGLIB_SEND_CALLBACK,
434
+ _quote($ulnSendMd, $storage)
435
+ );
436
+
437
+ return actions;
438
+ }
439
+
440
+ ;; @in_opcode Msglibs::OP::ULN_COMMIT_VERIFICATION
441
+ ;; @in frame
442
+ ;; @in $mdAddress { address: UlnConnectionAddress, md: Packet }
443
+ ;; @permissions permissionless
444
+ ;; @out_actions call commit on connection
445
+ tuple ulnCommitPacket(cell $mdAddress) impure inline method_id {
446
+ (cell $storage, tuple actions) = preamble();
447
+
448
+ actions~pushAction<call>(
449
+ $mdAddress.cl::get<address>(md::MdAddress::address),
450
+ UlnConnection::OP::ULN_CONNECTION_COMMIT_PACKET,
451
+ md::MdObj::New(
452
+ $mdAddress.cl::get<objRef>(md::MdAddress::md),
453
+ $storage.cl::get<objRef>(Uln::defaultUlnReceiveConfig)
454
+ )
455
+ );
456
+
457
+ return actions;
458
+ }
459
+
460
+ ;; @in_opcode Msglibs::OP::VERIFY
461
+ ;; @in external caller
462
+ ;; @in $mdAddress { address: UlnConnectionAddress, md: Verification }
463
+ ;; @permissions permissionless
464
+ ;; @out_actions call verify on connection
465
+ ;; @notice this is an optional function that will
466
+ ;; call ulnConnectionVerify on the connection using a default config
467
+ tuple ulnVerify(cell $mdAddress) impure inline method_id {
468
+ (cell $storage, tuple actions) = preamble();
469
+
470
+ actions~pushAction<call>(
471
+ $mdAddress.cl::get<address>(md::MdAddress::address),
472
+ UlnConnection::OP::ULN_CONNECTION_VERIFY,
473
+ md::ExtendedMd::New(
474
+ $mdAddress.cl::get<objRef>(md::MdAddress::md),
475
+ $storage.cl::get<objRef>(Uln::defaultUlnReceiveConfig),
476
+ getCaller()
477
+ )
478
+ );
479
+
480
+ return actions;
481
+ }
482
+
483
+ () _setWorkerInfo(cell $workerFeelibInfo) impure inline_ref {
484
+ cell $storage = getContractStorage();
485
+ int workerAddress = $workerFeelibInfo.cl::get<address>(UlnWorkerFeelibInfo::workerAddress);
486
+
487
+ ;; Restrict the size of the new storage to prevent DoS of our contract storage.
488
+ ;; The total worker bytecode size is capped by UlnManager::CONST::MAX_CUMULATIVE_BYTECODE_CELLS
489
+ ;; and enforced by the UlnManager, so here the only thing we need to check is the storage size
490
+ ;; of the workers, excluding their bytecode
491
+ (_, _, _, int success) = compute_data_size?(
492
+ $workerFeelibInfo.cl::set(UlnWorkerFeelibInfo::workerFeelibBytecode, empty_cell()),
493
+ Uln::WorkerFeelibInfo::MaxCells
494
+ );
495
+
496
+ throw_unless(Uln::ERROR::invalidWorkerStorage, success);
497
+
498
+ setContractStorage(
499
+ $storage
500
+ .cl::nestedDict256::setRef(
501
+ Uln::workerFeelibInfos,
502
+ workerAddress,
503
+ $workerFeelibInfo
504
+ )
505
+ );
506
+ }
507
+
508
+ tuple updateWorkerFeelib(cell $UlnWorkerFeelibInfo) impure inline method_id {
509
+ (cell $storage, tuple actions) = preamble();
510
+ int workerAddress = $UlnWorkerFeelibInfo.cl::get<address>(UlnWorkerFeelibInfo::workerAddress);
511
+
512
+ (cell $existingWorkerFeelibInfo, int exists) = cl::nestedDict256::get<cellRef>(
513
+ $storage,
514
+ Uln::workerFeelibInfos,
515
+ workerAddress
516
+ );
517
+
518
+ ifnot (exists) {
519
+ int isAdmin = $UlnWorkerFeelibInfo.cl::get<bool>(UlnWorkerFeelibInfo::isAdmin);
520
+ int workerSlotField = isAdmin ? Uln::remainingAdminWorkerSlots : Uln::remainingWorkerSlots;
521
+ int remainingWorkerSlots = $storage.cl::get<uint16>(workerSlotField);
522
+
523
+ if (remainingWorkerSlots == 0) {
524
+ ;; exit early if there are no remaining worker slots
525
+ actions~pushAction<event>(
526
+ Uln::event::ULN_WORKER_SLOTS_FULL,
527
+ $UlnWorkerFeelibInfo
528
+ );
529
+ return actions;
530
+ }
531
+
532
+ ifnot (isAdmin) {
533
+ ;; if it doesn't exist, we must collect the initial rent deposit
534
+ int initialRent = $UlnWorkerFeelibInfo.cl::get<coins>(UlnWorkerFeelibInfo::rentBalance);
535
+
536
+ throw_unless(Uln::ERROR::insufficientRent, initialRent >= Uln::CONST::INITIAL_RENT_NANOS);
537
+
538
+ actions~pushAction<payment>(
539
+ getOwner(),
540
+ initialRent,
541
+ 0
542
+ );
543
+ }
544
+
545
+ $UlnWorkerFeelibInfo = $UlnWorkerFeelibInfo.cl::set(
546
+ UlnWorkerFeelibInfo::lastRentTimestamp,
547
+ now()
548
+ );
549
+
550
+ setContractStorage($storage.cl::set(workerSlotField, remainingWorkerSlots - 1));
551
+ } else {
552
+ ;; Do not allow workers to arbitrarily change their rent information
553
+ $UlnWorkerFeelibInfo = $UlnWorkerFeelibInfo
554
+ .cl::set(
555
+ UlnWorkerFeelibInfo::rentBalance,
556
+ $existingWorkerFeelibInfo.cl::get<coins>(UlnWorkerFeelibInfo::rentBalance)
557
+ )
558
+ .cl::set(
559
+ UlnWorkerFeelibInfo::lastRentTimestamp,
560
+ $existingWorkerFeelibInfo.cl::get<uint64>(UlnWorkerFeelibInfo::lastRentTimestamp)
561
+ );
562
+ }
563
+
564
+ _setWorkerInfo($UlnWorkerFeelibInfo);
565
+
566
+ actions~pushAction<event>(
567
+ Uln::event::ULN_WORKER_REGISTERED,
568
+ $UlnWorkerFeelibInfo
569
+ );
570
+
571
+ return actions;
572
+ }
573
+
574
+ tuple deregisterWorkerFeelib(cell $empty) impure inline method_id {
575
+ (cell $storage, tuple actions) = preamble();
576
+
577
+ int workerAddress = getCaller();
578
+ (cell $UlnWorkerFeelibInfo, int exists) = cl::nestedDict256::get<cellRef>(
579
+ $storage,
580
+ Uln::workerFeelibInfos,
581
+ workerAddress
582
+ );
583
+
584
+ if (exists) {
585
+ setContractStorage(
586
+ _removeWorker($storage, $UlnWorkerFeelibInfo)
587
+ );
588
+ actions~pushAction<event>(
589
+ Uln::event::ULN_WORKER_DEREGISTERED,
590
+ $UlnWorkerFeelibInfo
591
+ );
592
+ }
593
+
594
+ return actions;
595
+ }
596
+
597
+ ;; This function handles ALL worker configs including priceFeed updates
598
+ ;; @out_actions event
599
+ tuple setWorkerFeelibStorage(cell $newStorage) impure inline method_id {
600
+ (cell $storage, tuple actions) = preamble();
601
+
602
+ (cell $workerInfo, int exists) = $storage.cl::nestedDict256::get<cellRef>(
603
+ Uln::workerFeelibInfos,
604
+ getCaller()
605
+ );
606
+ throw_unless(Uln::ERROR::nonexistentWorker, exists);
607
+
608
+ cell $updatedWorkerInfo = $workerInfo.cl::set(
609
+ UlnWorkerFeelibInfo::workerFeelibStorage,
610
+ $newStorage
611
+ );
612
+
613
+ ;; _setWorkerInfo does size assertions on worker storage
614
+ _setWorkerInfo($updatedWorkerInfo);
615
+
616
+ setContractStorage(
617
+ $storage
618
+ .cl::nestedDict256::setRef(
619
+ Uln::workerFeelibInfos,
620
+ getCaller(),
621
+ $updatedWorkerInfo
622
+ )
623
+ );
624
+
625
+ actions~pushAction<event>(
626
+ Uln::event::ULN_WORKER_STORAGE_SET,
627
+ $updatedWorkerInfo
628
+ );
629
+
630
+ actions~pushAction<call>(
631
+ getCaller(),
632
+ Uln::OP::SET_WORKER_FEELIB_STORAGE_CALLBACK,
633
+ $newStorage
634
+ );
635
+
636
+ return actions;
637
+ }
638
+
639
+ tuple refillWorkerRent(cell $rentRefill) {
640
+ (cell $storage, tuple actions) = preamble();
641
+
642
+ int workerAddress = $rentRefill.cl::get<address>(md::RentRefill::address);
643
+ int amount = $rentRefill.cl::get<coins>(md::RentRefill::amount);
644
+ (cell $workerInfo, int exists) = cl::nestedDict256::get<cellRef>(
645
+ $storage,
646
+ Uln::workerFeelibInfos,
647
+ workerAddress
648
+ );
649
+
650
+ throw_unless(Uln::ERROR::nonexistentWorker, exists);
651
+
652
+ int currentRentBalance = $workerInfo.cl::get<coins>(UlnWorkerFeelibInfo::rentBalance);
653
+
654
+ _setWorkerInfo(
655
+ $workerInfo.cl::set(UlnWorkerFeelibInfo::rentBalance, currentRentBalance + amount)
656
+ );
657
+
658
+ actions~pushAction<payment>(
659
+ getOwner(),
660
+ amount,
661
+ 0
662
+ );
663
+
664
+ actions~pushAction<event>(
665
+ Uln::event::ULN_WORKER_RENT_REFILLED,
666
+ $rentRefill
667
+ );
668
+
669
+ return actions;
670
+ }
671
+
672
+ tuple collectWorkerRent(cell $setAddress) impure inline method_id {
673
+ (cell $storage, tuple actions) = preamble();
674
+
675
+ (cell $workerInfo, int exists) = cl::nestedDict256::get<cellRef>(
676
+ $storage,
677
+ Uln::workerFeelibInfos,
678
+ $setAddress.cl::get<address>(md::SetAddress::address)
679
+ );
680
+
681
+ throw_unless(Uln::ERROR::nonexistentWorker, exists);
682
+
683
+ ;; Admins do not pay rent
684
+ if ($workerInfo.cl::get<bool>(UlnWorkerFeelibInfo::isAdmin)) {
685
+ return emptyActions();
686
+ }
687
+
688
+ int currentTimestamp = now();
689
+ int elapsedTimestamp = currentTimestamp - $workerInfo.cl::get<uint64>(UlnWorkerFeelibInfo::lastRentTimestamp);
690
+ throw_unless(Uln::ERROR::invalidTimestamp, elapsedTimestamp > 0);
691
+
692
+ int totalRentOwed = elapsedTimestamp * Uln::CONST::RENT_NANOS_PER_SECOND;
693
+ int currentRentBalance = $workerInfo.cl::get<coins>(UlnWorkerFeelibInfo::rentBalance);
694
+
695
+ ;; if rentBalance is greater than totalRentOwed, we can update rentBalance and lastRentTimestamp
696
+ ;; else we must delete(evict) the worker from the workerInfos
697
+ if (currentRentBalance >= totalRentOwed) {
698
+ $workerInfo = $workerInfo
699
+ .cl::set(UlnWorkerFeelibInfo::rentBalance, currentRentBalance - totalRentOwed)
700
+ .cl::set(UlnWorkerFeelibInfo::lastRentTimestamp, currentTimestamp);
701
+
702
+ ;; update workerInfo in storage
703
+ _setWorkerInfo($workerInfo);
704
+
705
+ actions~pushAction<event>(
706
+ Uln::event::ULN_COLLECT_WORKER_RENT,
707
+ $workerInfo
708
+ );
709
+ } else {
710
+ setContractStorage(
711
+ _removeWorker($storage, $workerInfo)
712
+ );
713
+
714
+ actions~pushAction<event>(
715
+ Uln::event::ULN_WORKER_EVICTED,
716
+ $workerInfo
717
+ );
718
+ }
719
+
720
+ return actions;
721
+ }
722
+
723
+ tuple setDefaultUlnSendConfig(cell $ulnSendConfig) impure inline method_id {
724
+ (cell $storage, tuple actions) = preamble();
725
+
726
+ cell $sanitizedUlnSendConfig = UlnSendConfig::sanitize($ulnSendConfig);
727
+
728
+ setContractStorage(
729
+ $storage.cl::set(
730
+ Uln::defaultUlnSendConfig,
731
+ $sanitizedUlnSendConfig
732
+ )
733
+ );
734
+
735
+ actions~pushAction<event>(
736
+ Uln::event::ULN_DEFAULT_SEND_CONFIG_SET,
737
+ $sanitizedUlnSendConfig
738
+ );
739
+
740
+ return actions;
741
+ }
742
+
743
+ tuple setDefaultUlnReceiveConfig(cell $ulnReceiveConfig) impure inline method_id {
744
+ (cell $storage, tuple actions) = preamble();
745
+
746
+ cell $sanitizedUlnReceiveConfig = UlnReceiveConfig::sanitize($ulnReceiveConfig);
747
+
748
+ setContractStorage(
749
+ $storage.cl::set(
750
+ Uln::defaultUlnReceiveConfig,
751
+ $sanitizedUlnReceiveConfig
752
+ )
753
+ );
754
+ actions~pushAction<event>(
755
+ Uln::event::ULN_DEFAULT_RECEIVE_CONFIG_SET,
756
+ $sanitizedUlnReceiveConfig
757
+ );
758
+
759
+ return actions;
760
+ }
761
+
762
+ tuple setTreasuryFeeBps(cell $treasuryFeeBps) impure inline method_id {
763
+ (cell $storage, tuple actions) = preamble();
764
+
765
+ int treasuryFeeBps = $treasuryFeeBps.cl::get<uint16>(md::TreasuryFeeBps::treasuryFeeBps);
766
+
767
+ throw_unless(Uln::ERROR::invalidTreasuryFeeBps, treasuryFeeBps <= 10000);
768
+
769
+ setContractStorage(
770
+ $storage.cl::set(
771
+ Uln::treasuryFeeBps,
772
+ treasuryFeeBps
773
+ )
774
+ );
775
+
776
+ actions~pushAction<event>(
777
+ Uln::event::ULN_TREASURY_FEE_BPS_SET,
778
+ $treasuryFeeBps
779
+ );
780
+
781
+ return actions;
782
+ }
783
+
784
+ ;; Send the default config to the ULN connection to allow it to garbage collect
785
+ ;; attestations from DVNs that were removed from the configuration
786
+ tuple garbageCollectInvalidAttestations(cell $mdAddress) impure inline method_id {
787
+ (cell $storage, tuple actions) = preamble();
788
+
789
+ actions~pushAction<call>(
790
+ $mdAddress.cl::get<address>(md::MdAddress::address),
791
+ UlnConnection::OP::GARBAGE_COLLECT_INVALID_ATTESTATIONS,
792
+ md::MdObj::New(
793
+ $mdAddress.cl::get<objRef>(md::MdAddress::md),
794
+ $storage.cl::get<objRef>(Uln::defaultUlnReceiveConfig)
795
+ )
796
+ );
797
+
798
+ return actions;
799
+ }
800
+
801
+ (int, int, int) version() impure method_id {
802
+ return (3, 0, 2);
803
+ }