@layerzerolabs/layerzero-v2-ton 3.0.19-ton.0 → 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.
- package/CHANGELOG.md +6 -0
- package/build/AllStorages.compiled.json +1 -1
- package/build/AllStorages.test.compiled.json +1 -1
- package/build/BaseContract.test.compiled.json +1 -1
- package/build/Channel.compiled.json +1 -1
- package/build/Channel.permissions.test.compiled.json +1 -1
- package/build/ChannelBurn.test.compiled.json +1 -1
- package/build/ChannelCommitPacket.test.compiled.json +1 -1
- package/build/ChannelConfig.test.compiled.json +1 -1
- package/build/ChannelInitialize.test.compiled.json +1 -1
- package/build/ChannelMsglibIntegration.test.compiled.json +1 -1
- package/build/ChannelMsglibSendCallback.test.compiled.json +1 -1
- package/build/ChannelNilify.test.compiled.json +1 -1
- package/build/ChannelReceive.test.compiled.json +1 -1
- package/build/ChannelReceiveCallback.test.compiled.json +1 -1
- package/build/ChannelReceiveView.test.compiled.json +1 -1
- package/build/ChannelSend.test.compiled.json +1 -1
- package/build/Classlib.test.compiled.json +1 -1
- package/build/ComputeDataSizeGas.test.compiled.json +1 -1
- package/build/Connection.compiled.json +1 -1
- package/build/Controller.assertions.test.compiled.json +1 -1
- package/build/Controller.compiled.json +1 -1
- package/build/Controller.permissions.test.compiled.json +1 -1
- package/build/Controller.test.compiled.json +1 -1
- package/build/Counter.compiled.json +1 -1
- package/build/Counter.permissions.test.compiled.json +1 -1
- package/build/Counter.setters.test.compiled.json +1 -1
- package/build/Counter.test.compiled.json +1 -1
- package/build/Dvn.compiled.json +1 -1
- package/build/Dvn.test.compiled.json +1 -1
- package/build/DvnFeeLib.compiled.json +1 -1
- package/build/DvnPermissions.test.compiled.json +1 -1
- package/build/Endpoint.compiled.json +1 -1
- package/build/Endpoint.permissions.test.compiled.json +1 -1
- package/build/Endpoint.test.compiled.json +1 -1
- package/build/EndpointSetEpConfigDefaults.test.compiled.json +1 -1
- package/build/Executor.compiled.json +1 -1
- package/build/Executor.test.compiled.json +1 -1
- package/build/ExecutorFeeLib.compiled.json +1 -1
- package/build/ExecutorPermissions.test.compiled.json +1 -1
- package/build/LzClasses.test.compiled.json +1 -1
- package/build/LzUtil.test.compiled.json +1 -1
- package/build/MsgData.test.compiled.json +1 -1
- package/build/MsglibPacketCodec.test.compiled.json +1 -1
- package/build/PipelinedOutOfOrder.test.compiled.json +1 -1
- package/build/PriceFeedCache.compiled.json +1 -1
- package/build/PriceFeedCache.permissions.test.compiled.json +1 -1
- package/build/PriceFeedCache.test.compiled.json +1 -1
- package/build/Proxy.compiled.json +1 -1
- package/build/Proxy.permissions.test.compiled.json +1 -1
- package/build/Proxy.test.compiled.json +1 -1
- package/build/SmlConnection.compiled.json +1 -1
- package/build/SmlConnection.permissions.test.compiled.json +1 -1
- package/build/SmlConnection.test.compiled.json +1 -1
- package/build/SmlManager.compiled.json +1 -1
- package/build/SmlManager.permissions.test.compiled.json +1 -1
- package/build/SmlManager.test.compiled.json +1 -1
- package/build/Uln.compiled.json +1 -1
- package/build/Uln.test.compiled.json +1 -1
- package/build/UlnConnection.compiled.json +1 -1
- package/build/UlnConnection.test.compiled.json +1 -1
- package/build/UlnConnectionPermissions.test.compiled.json +1 -1
- package/build/UlnManagement.test.compiled.json +1 -1
- package/build/UlnManager.compiled.json +1 -1
- package/build/UlnManager.test.compiled.json +1 -1
- package/build/UlnManagerPermissions.test.compiled.json +1 -1
- package/build/UlnManagerUtil.test.compiled.json +1 -1
- package/build/UlnPermissions.test.compiled.json +1 -1
- package/build/UlnReceiveConfig.test.compiled.json +1 -1
- package/build/UlnSend.test.compiled.json +1 -1
- package/build/UlnSendConfig.test.compiled.json +1 -1
- package/build/UlnSendWithDvnFeeLib.test.compiled.json +1 -1
- package/build/UlnSendWithExecFeeLib.test.compiled.json +1 -1
- package/build/UlnSendWorkerFactory.test.compiled.json +1 -1
- package/build/UlnUtil.test.compiled.json +1 -1
- package/build/WorkerCore.test.compiled.json +1 -1
- package/build/badFeeLib1.test.compiled.json +1 -1
- package/build/badFeeLib10.test.compiled.json +1 -1
- package/build/badFeeLib11.test.compiled.json +1 -1
- package/build/badFeeLib12.test.compiled.json +1 -1
- package/build/badFeeLib2.test.compiled.json +1 -1
- package/build/badFeeLib3.test.compiled.json +1 -1
- package/build/badFeeLib4.test.compiled.json +1 -1
- package/build/badFeeLib5.test.compiled.json +1 -1
- package/build/badFeeLib6.test.compiled.json +1 -1
- package/build/badFeeLib7.test.compiled.json +1 -1
- package/build/badFeeLib8.test.compiled.json +1 -1
- package/build/badFeeLib9.test.compiled.json +1 -1
- package/package.json +5 -5
- package/src/classes/msgdata/LzReceiveStatus.fc +0 -1
- package/src/funC++/actions/call.fc +1 -0
- package/src/funC++/actions/deploy.fc +0 -1
- package/src/funC++/actions/destroy.fc +0 -1
- package/src/funC++/actions/dispatch.fc +0 -1
- package/src/funC++/actions/event.fc +0 -1
- package/src/funC++/actions/payment.fc +0 -1
- package/src/funC++/actions/sendJettons.fc +0 -1
- package/src/funC++/actions/utils.fc +0 -2
- package/src/funC++/baseInterface.fc +0 -2
- package/src/funC++/classlib.fc +0 -36
- package/src/funC++/contractMain.fc +2 -8
- package/src/funC++/dataStructures/DeterministicInsertionCircularQueue.fc +0 -1
- package/src/funC++/dataStructures/PipelinedOutOfOrder.fc +0 -1
- package/src/funC++/handlerCore.fc +2 -6
- package/src/funC++/stringlib.fc +0 -2
- package/src/funC++/testutils.fc +0 -1
- package/src/funC++/txnContext.fc +1 -1
- package/src/funC++/utils.fc +35 -0
- package/src/protocol/channel/callbackOpcodes.fc +10 -0
- package/src/protocol/channel/handler.fc +1032 -0
- package/src/protocol/channel/interface.fc +60 -0
- package/src/protocol/channel/main.fc +39 -0
- package/src/protocol/channel/storage.fc +55 -0
- package/src/protocol/controller/handler.fc +347 -0
- package/src/protocol/controller/interface.fc +25 -0
- package/src/protocol/controller/main.fc +29 -0
- package/src/protocol/controller/storage.fc +31 -0
- package/src/protocol/core/abstract/protocolHandler.fc +110 -0
- package/src/protocol/core/abstract/protocolMain.fc +30 -0
- package/src/protocol/core/baseStorage.fc +1 -2
- package/src/protocol/endpoint/handler.fc +426 -0
- package/src/protocol/endpoint/interface.fc +20 -0
- package/src/protocol/endpoint/main.fc +23 -0
- package/src/protocol/interfaces.fc +4 -0
- package/src/protocol/msglibs/BytesDecoder.fc +135 -0
- package/src/protocol/msglibs/BytesEncoder.fc +150 -0
- package/src/protocol/msglibs/interface.fc +16 -0
- package/src/protocol/msglibs/simpleMsglib/smlConnection/handler.fc +125 -0
- package/src/protocol/msglibs/simpleMsglib/smlConnection/interface.fc +3 -0
- package/src/protocol/msglibs/simpleMsglib/smlConnection/main.fc +19 -0
- package/src/protocol/msglibs/simpleMsglib/smlConnection/storage.fc +20 -0
- package/src/protocol/msglibs/simpleMsglib/smlManager/handler.fc +281 -0
- package/src/protocol/msglibs/simpleMsglib/smlManager/interface.fc +14 -0
- package/src/protocol/msglibs/simpleMsglib/smlManager/main.fc +24 -0
- package/src/protocol/msglibs/simpleMsglib/smlManager/storage.fc +38 -0
- package/src/protocol/msglibs/ultralightnode/callbackOpcodes.fc +1 -0
- package/src/protocol/msglibs/ultralightnode/feeLibInterface.fc +10 -0
- package/src/protocol/msglibs/ultralightnode/feeLibUtils.fc +51 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/Attestation.fc +49 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/DvnFeesPaidEvent.fc +26 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/ExecutorFeePaidEvent.fc +23 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/InitUln.fc +18 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/InitUlnConnection.fc +62 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/InitUlnManager.fc +18 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/RentRefill.fc +18 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/SetAdminWorkerAddresses.fc +18 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/TreasuryFeeBps.fc +16 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnEvents.fc +26 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnReceiveConfig.fc +249 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnSend.fc +27 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnSendConfig.fc +170 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnVerification.fc +21 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnWorkerFeelibBytecode.fc +16 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnWorkerFeelibEvents.fc +58 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/UlnWorkerFeelibInfo.fc +56 -0
- package/src/protocol/msglibs/ultralightnode/msgdata/VerificationStatus.fc +18 -0
- package/src/protocol/msglibs/ultralightnode/uln/handler.fc +803 -0
- package/src/protocol/msglibs/ultralightnode/uln/interface.fc +63 -0
- package/src/protocol/msglibs/ultralightnode/uln/main.fc +37 -0
- package/src/protocol/msglibs/ultralightnode/uln/storage.fc +43 -0
- package/src/protocol/msglibs/ultralightnode/ulnConnection/handler.fc +600 -0
- package/src/protocol/msglibs/ultralightnode/ulnConnection/interface.fc +36 -0
- package/src/protocol/msglibs/ultralightnode/ulnConnection/main.fc +32 -0
- package/src/protocol/msglibs/ultralightnode/ulnConnection/storage.fc +49 -0
- package/src/protocol/msglibs/ultralightnode/ulnConnection/utils.fc +141 -0
- package/src/protocol/msglibs/ultralightnode/ulnManager/handler.fc +495 -0
- package/src/protocol/msglibs/ultralightnode/ulnManager/interface.fc +59 -0
- package/src/protocol/msglibs/ultralightnode/ulnManager/main.fc +40 -0
- package/src/protocol/msglibs/ultralightnode/ulnManager/storage.fc +44 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/common.fc +27 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/dvnFeeLib/handler.fc +80 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/dvnFeeLib/main.fc +4 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/dvnFeeLib/storage.fc +26 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/executorFeeLib/handler.fc +123 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/executorFeeLib/main.fc +4 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/executorFeeLib/storage.fc +29 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/main.fc +3 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/priceFeedFeeLib/main.fc +1 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/priceFeedFeeLib/storage.fc +39 -0
- package/src/protocol/msglibs/ultralightnode/workerFeeLibs/ulnSendWorkerV1.fc +363 -0
- package/src/workers/core/abstract/workerHandler.fc +150 -0
- package/src/workers/core/interface.fc +25 -0
- package/src/workers/core/workerCoreStorage.fc +44 -0
- package/src/workers/dvn/handler.fc +332 -0
- package/src/workers/dvn/interface.fc +25 -0
- package/src/workers/dvn/main.fc +36 -0
- package/src/workers/dvn/storage.fc +27 -0
- package/src/workers/executor/handler.fc +110 -0
- package/src/workers/executor/interface.fc +19 -0
- package/src/workers/executor/main.fc +26 -0
- package/src/workers/executor/storage.fc +19 -0
- package/src/workers/msgdata/ExecuteParams.fc +29 -0
- package/src/workers/msgdata/NativeDrop.fc +16 -0
- package/src/workers/msgdata/ProxyMessage.fc +20 -0
- package/src/workers/msgdata/SetDict.fc +20 -0
- package/src/workers/msgdata/SetQuorum.fc +20 -0
- package/src/workers/msgdata/SignedRequest.fc +18 -0
- package/src/workers/priceFeedCache/handler.fc +114 -0
- package/src/workers/priceFeedCache/interface.fc +4 -0
- package/src/workers/priceFeedCache/main.fc +25 -0
- package/src/workers/priceFeedCache/storage.fc +21 -0
- package/src/workers/proxy/handler.fc +81 -0
- package/src/workers/proxy/interface.fc +11 -0
- package/src/workers/proxy/main.fc +17 -0
- package/src/workers/proxy/storage.fc +21 -0
- package/tests/testMain.fc +0 -1
|
@@ -0,0 +1,1032 @@
|
|
|
1
|
+
#include "callbackOpcodes.fc";
|
|
2
|
+
|
|
3
|
+
#include "../core/abstract/protocolHandler.fc";
|
|
4
|
+
|
|
5
|
+
#include "../../funC++/actions/dispatch.fc";
|
|
6
|
+
#include "../../funC++/actions/event.fc";
|
|
7
|
+
|
|
8
|
+
#include "../../classes/lz/EpConfig.fc";
|
|
9
|
+
#include "../../classes/lz/Packet.fc";
|
|
10
|
+
#include "../../classes/lz/Path.fc";
|
|
11
|
+
#include "../../classes/lz/ReceiveEpConfig.fc";
|
|
12
|
+
#include "../../classes/lz/SendEpConfig.fc";
|
|
13
|
+
|
|
14
|
+
#include "../../classes/msgdata/ChannelNonceInfo.fc";
|
|
15
|
+
#include "../../classes/msgdata/CoinsAmount.fc";
|
|
16
|
+
#include "../../classes/msgdata/ExtendedMd.fc";
|
|
17
|
+
#include "../../classes/msgdata/LzReceivePrepare.fc";
|
|
18
|
+
#include "../../classes/msgdata/LzReceiveStatus.fc";
|
|
19
|
+
#include "../../classes/msgdata/LzReceivePrepare.fc";
|
|
20
|
+
#include "../../classes/msgdata/LzSend.fc";
|
|
21
|
+
#include "../../classes/msgdata/MdAddress.fc";
|
|
22
|
+
#include "../../classes/msgdata/MdObj.fc";
|
|
23
|
+
#include "../../classes/msgdata/MessagingReceipt.fc";
|
|
24
|
+
#include "../../classes/msgdata/MsglibSendCallback.fc";
|
|
25
|
+
#include "../../classes/msgdata/Nonce.fc";
|
|
26
|
+
#include "../../classes/msgdata/PacketId.fc";
|
|
27
|
+
#include "../../classes/msgdata/PacketSent.fc";
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
#include "../../funC++/dataStructures/DeterministicInsertionCircularQueue.fc";
|
|
31
|
+
#include "../../funC++/dataStructures/PipelinedOutOfOrder.fc";
|
|
32
|
+
|
|
33
|
+
#include "../interfaces.fc";
|
|
34
|
+
#include "../msglibs/interface.fc";
|
|
35
|
+
#include "interface.fc";
|
|
36
|
+
#include "storage.fc";
|
|
37
|
+
|
|
38
|
+
;;; ================INTERFACE FUNCTIONS=====================
|
|
39
|
+
|
|
40
|
+
int _getEventSink() inline {
|
|
41
|
+
return getContractStorage()
|
|
42
|
+
.cl::get<objRef>(Channel::baseStorage)
|
|
43
|
+
.cl::get<address>(BaseStorage::owner);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
;;; ==========================HELPER FUNCTIONS=====================================
|
|
47
|
+
|
|
48
|
+
() _assertEqualPaths(cell $path1, cell $path2) impure inline {
|
|
49
|
+
throw_unless(Channel::ERROR::wrongPath, $path1.cl::hash() == $path2.cl::hash());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
;; @info The send request queue (Channel::sendRequestQueue) is a DeterministicInsertionCircularQueue
|
|
53
|
+
;; that stores a mapping from requestId => hash of LzSend object.
|
|
54
|
+
;; {_build, _read}SendRequestQueueEntry functions are helper functions that
|
|
55
|
+
;; serialize and deserialize the 256-bit hash that is stored in the DICQueue
|
|
56
|
+
cell _buildSendRequestQueueEntry(cell $lzSend) inline method_id {
|
|
57
|
+
return begin_cell().store_uint256($lzSend.cl::hash()).end_cell();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
int _readSendRequestQueueEntry(cell contents) inline method_id {
|
|
61
|
+
if (contents.is_null()) {
|
|
62
|
+
return 0;
|
|
63
|
+
} elseif (contents.cell_is_empty()) {
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
return contents.begin_parse().preload_uint(256);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
;; returns boolean committable, (packet or null)
|
|
70
|
+
(int, cell) _nonceCommittable(int incomingNonce) impure inline method_id {
|
|
71
|
+
throw_if(Channel::ERROR::invalidNonce, incomingNonce <= 0);
|
|
72
|
+
|
|
73
|
+
cell $storage = getContractStorage();
|
|
74
|
+
|
|
75
|
+
cell $executePOOO = $storage.cl::get<objRef>(Channel::executePOOO);
|
|
76
|
+
int firstUnexecutedNonce = $executePOOO.cl::get<uint64>(POOO::nextEmpty);
|
|
77
|
+
|
|
78
|
+
(int actualKey, cell $packet, int status, int exists) = DeterministicInsertionCircularQueue::get(
|
|
79
|
+
$storage.cl::get<cellRef>(Channel::executionQueue),
|
|
80
|
+
incomingNonce
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (
|
|
84
|
+
(incomingNonce == firstUnexecutedNonce)
|
|
85
|
+
& (actualKey == incomingNonce)
|
|
86
|
+
& (status != ExecutionQueue::executing)
|
|
87
|
+
) {
|
|
88
|
+
;; short-circuit for efficiency in the common case
|
|
89
|
+
return (true, exists ? $packet : null());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
;; condition 1 & 2: must be within the window
|
|
93
|
+
;; condition 3: must not be executing
|
|
94
|
+
if (
|
|
95
|
+
(incomingNonce >= firstUnexecutedNonce)
|
|
96
|
+
& (incomingNonce <= POOO::maxSettableBit($executePOOO))
|
|
97
|
+
& (status != ExecutionQueue::executing)
|
|
98
|
+
) {
|
|
99
|
+
;; this is nested because funC doesn't support short-circuiting boolean/bitwise ops
|
|
100
|
+
;; condition 4: must not be executed
|
|
101
|
+
ifnot (POOO::isBitSet($executePOOO, incomingNonce)) {
|
|
102
|
+
return (true, exists ? $packet : null());
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return (false, null());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
cell _getExecutablePacket(int incomingNonce) impure inline method_id {
|
|
110
|
+
(int isCommittable, cell $packet) = _nonceCommittable(incomingNonce);
|
|
111
|
+
int firstUncommittedNonce = getContractStorage()
|
|
112
|
+
.cl::get<objRef>(Channel::commitPOOO)
|
|
113
|
+
.cl::get<uint64>(POOO::nextEmpty);
|
|
114
|
+
|
|
115
|
+
throw_if(
|
|
116
|
+
Channel::ERROR::notExecutable,
|
|
117
|
+
((~ isCommittable) | (incomingNonce >= firstUncommittedNonce) | $packet.is_null())
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return $packet;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
() _assertNonceCommittable(int incomingNonce) impure inline {
|
|
124
|
+
;; Split into multiple lines to fix false-positive linter warning
|
|
125
|
+
(
|
|
126
|
+
int isCommittable,
|
|
127
|
+
_
|
|
128
|
+
) = _nonceCommittable(incomingNonce);
|
|
129
|
+
|
|
130
|
+
throw_unless(Channel::ERROR::notCommittable, isCommittable);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
;;; ==========================VIEW FUNCTIONS=====================================
|
|
134
|
+
|
|
135
|
+
int _viewInboundNonce() impure method_id {
|
|
136
|
+
return getContractStorage()
|
|
137
|
+
.cl::get<objRef>(Channel::commitPOOO)
|
|
138
|
+
.cl::get<uint64>(POOO::nextEmpty) - 1;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
int _viewExecutionStatus(int incomingNonce) impure method_id {
|
|
142
|
+
cell $storage = getContractStorage();
|
|
143
|
+
|
|
144
|
+
cell $executePOOO = $storage.cl::get<objRef>(Channel::executePOOO);
|
|
145
|
+
int firstUnexecutedNonce = $executePOOO.cl::get<uint64>(POOO::nextEmpty);
|
|
146
|
+
cell $commitPOOO = $storage.cl::get<objRef>(Channel::commitPOOO);
|
|
147
|
+
int firstUncommittedNonce = $commitPOOO.cl::get<uint64>(POOO::nextEmpty);
|
|
148
|
+
int inboundNonce = _viewInboundNonce();
|
|
149
|
+
|
|
150
|
+
int executed = incomingNonce < firstUnexecutedNonce;
|
|
151
|
+
if ((~ executed) & (incomingNonce < (firstUnexecutedNonce + MAX_CELL_BITS))) {
|
|
152
|
+
executed = executed | $executePOOO.POOO::isBitSet(incomingNonce);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
int committed = incomingNonce < firstUncommittedNonce;
|
|
156
|
+
if ((~ committed) & (incomingNonce < (firstUncommittedNonce + MAX_CELL_BITS))) {
|
|
157
|
+
committed = committed | $commitPOOO.POOO::isBitSet(incomingNonce);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
ifnot (committed) {
|
|
161
|
+
return ExecutionStatus::uncommitted;
|
|
162
|
+
} elseif (executed) {
|
|
163
|
+
return ExecutionStatus::executed;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
(_, _, int status, _) = DeterministicInsertionCircularQueue::get(
|
|
167
|
+
$storage.cl::get<cellRef>(Channel::executionQueue),
|
|
168
|
+
incomingNonce
|
|
169
|
+
);
|
|
170
|
+
if (status == ExecutionQueue::executing) {
|
|
171
|
+
return ExecutionStatus::executing;
|
|
172
|
+
} elseif (incomingNonce <= inboundNonce) {
|
|
173
|
+
return ExecutionStatus::executable;
|
|
174
|
+
}
|
|
175
|
+
return ExecutionStatus::committedNotExecutable;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
;;; ================INTERFACE FUNCTIONS=====================
|
|
179
|
+
|
|
180
|
+
(cell, tuple) _initialize(cell $md) impure inline {
|
|
181
|
+
(cell $storage, tuple actions) = preamble();
|
|
182
|
+
cell $path = $storage.cl::get<objRef>(Channel::path);
|
|
183
|
+
|
|
184
|
+
throw_if(
|
|
185
|
+
Channel::ERROR::wrongPath,
|
|
186
|
+
($path.cl::get<uint32>(lz::Path::srcEid) == 0)
|
|
187
|
+
| ($path.cl::get<address>(lz::Path::srcOApp) == NULLADDRESS)
|
|
188
|
+
| ($path.cl::get<uint32>(lz::Path::dstEid) == 0)
|
|
189
|
+
| ($path.cl::get<address>(lz::Path::dstOApp) == NULLADDRESS)
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
$storage
|
|
194
|
+
.cl::set(Channel::executionQueue, DeterministicInsertionCircularQueue::create())
|
|
195
|
+
.cl::set(Channel::sendRequestQueue, DeterministicInsertionCircularQueue::create()),
|
|
196
|
+
actions
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
;;; ================PERMISSION FUNCTIONS=====================
|
|
201
|
+
|
|
202
|
+
() _assertEndpoint() impure inline {
|
|
203
|
+
throw_unless(
|
|
204
|
+
Channel::ERROR::onlyEndpoint,
|
|
205
|
+
getCaller() == getContractStorage().cl::get<address>(Channel::endpointAddress)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
;; this function is purposely designed to be maximally efficient when using a
|
|
210
|
+
;; custom configuration and less efficient when using a default configuration
|
|
211
|
+
() _assertSendMsglib(cell $mdAddress) impure inline {
|
|
212
|
+
cell epConfigOApp = getContractStorage().cl::get<objRef>(Channel::epConfigOApp);
|
|
213
|
+
|
|
214
|
+
;; Resolve the actual sendMsglib address at the time of request.
|
|
215
|
+
;; This function assumes the messagelib is not malicious or man-in-the-middle attacking,
|
|
216
|
+
;; as those cases are asserted in the handler itself.
|
|
217
|
+
int sendMsglibAddress = $mdAddress
|
|
218
|
+
.cl::get<objRef>(md::MdAddress::md)
|
|
219
|
+
.cl::get<objRef>(md::MsglibSendCallback::lzSend)
|
|
220
|
+
.cl::get<address>(md::LzSend::sendMsglib);
|
|
221
|
+
|
|
222
|
+
throw_unless(Channel::ERROR::onlyApprovedSendMsglib, getCaller() == sendMsglibAddress);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
() _assertOApp() impure inline {
|
|
226
|
+
throw_unless(
|
|
227
|
+
Channel::ERROR::onlyOApp,
|
|
228
|
+
getCaller() == getContractStorage()
|
|
229
|
+
.cl::get<objRef>(Channel::path)
|
|
230
|
+
.cl::get<uint256>(lz::Path::srcOApp)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
() _checkPermissions(int op, cell $md) impure inline {
|
|
235
|
+
if (op == Channel::OP::LZ_RECEIVE_PREPARE) {
|
|
236
|
+
;; open and public calls
|
|
237
|
+
return ();
|
|
238
|
+
} elseif (
|
|
239
|
+
(op == Channel::OP::CHANNEL_SEND)
|
|
240
|
+
| (op == Channel::OP::CHANNEL_COMMIT_PACKET)
|
|
241
|
+
) {
|
|
242
|
+
return _assertEndpoint();
|
|
243
|
+
} elseif (op == Channel::OP::MSGLIB_SEND_CALLBACK) {
|
|
244
|
+
return _assertSendMsglib($md);
|
|
245
|
+
} elseif (
|
|
246
|
+
(op == Channel::OP::LZ_RECEIVE_LOCK)
|
|
247
|
+
| (op == Channel::OP::LZ_RECEIVE_EXECUTE_CALLBACK)
|
|
248
|
+
) {
|
|
249
|
+
return _assertOApp();
|
|
250
|
+
} elseif (op == Channel::OP::DEPOSIT_ZRO) {
|
|
251
|
+
return assertOwner();
|
|
252
|
+
} elseif (
|
|
253
|
+
(op == Channel::OP::NOTIFY_PACKET_EXECUTED)
|
|
254
|
+
| (op == Channel::OP::SYNC_MSGLIB_CONNECTION)
|
|
255
|
+
) {
|
|
256
|
+
return ();
|
|
257
|
+
} elseif (op == Channel::OP::SET_EP_CONFIG_OAPP) {
|
|
258
|
+
return _assertEndpoint();
|
|
259
|
+
} elseif (
|
|
260
|
+
;; Management functions are all gated by OApp
|
|
261
|
+
(op == Channel::OP::NILIFY)
|
|
262
|
+
| (op == Channel::OP::BURN)
|
|
263
|
+
| (op == Channel::OP::FORCE_ABORT)
|
|
264
|
+
) {
|
|
265
|
+
return _assertOApp();
|
|
266
|
+
} elseif (op == Channel::OP::EMIT_LZ_RECEIVE_ALERT) {
|
|
267
|
+
return ();
|
|
268
|
+
} else {
|
|
269
|
+
;; we must put a check for all opcodes to make sure we don't
|
|
270
|
+
;; mistakenly miss an opp code's permissions
|
|
271
|
+
throw(BaseInterface::ERROR::invalidOpcode);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
;;; ==========================HANDLERS=====================================
|
|
276
|
+
|
|
277
|
+
;; @in endpoint/handler.fc/setEpConfig
|
|
278
|
+
;; @out controller/handler.fc/emit_event
|
|
279
|
+
;; @md EpConfig
|
|
280
|
+
tuple setEpConfigOApp(cell $epConfigOApp) impure inline method_id {
|
|
281
|
+
(cell $storage, tuple actions) = preamble();
|
|
282
|
+
|
|
283
|
+
int configValidity = $epConfigOApp.lz::EpConfig::isValid();
|
|
284
|
+
throw_if(configValidity, configValidity != lz::EpConfig::VALID);
|
|
285
|
+
|
|
286
|
+
setContractStorage($storage.cl::set(Channel::epConfigOApp, $epConfigOApp));
|
|
287
|
+
|
|
288
|
+
actions~pushAction<event>(Channel::event::EP_CFG_OAPP_SET, $epConfigOApp);
|
|
289
|
+
return actions;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
;;; ==========================================
|
|
293
|
+
;; Send flow
|
|
294
|
+
;; @in: endpoint/handler.fc/quote
|
|
295
|
+
;; @in_md: MdObj(lzSend, defaultEpConfig)
|
|
296
|
+
;; @out: msglib/handler.fc/quote
|
|
297
|
+
;; @out_md: $lzSend
|
|
298
|
+
tuple channelSend(cell $mdObj) impure inline method_id {
|
|
299
|
+
(cell $storage, tuple actions) = preamble();
|
|
300
|
+
|
|
301
|
+
cell $lzSend = $mdObj.cl::get<objRef>(md::MdObj::md);
|
|
302
|
+
;; assert the size and structure of the incoming lzSend message
|
|
303
|
+
lz::Packet::assertValidSendMessage($lzSend.cl::get<objRef>(md::LzSend::packet));
|
|
304
|
+
|
|
305
|
+
;; Resolve the desired send msglib and send msglib connection
|
|
306
|
+
cell $epConfigOApp = $storage.cl::get<objRef>(Channel::epConfigOApp);
|
|
307
|
+
int sendMsglib = $epConfigOApp.cl::get<address>(lz::EpConfig::sendMsglib);
|
|
308
|
+
int sendMsglibConnection = $epConfigOApp.cl::get<address>(lz::EpConfig::sendMsglibConnection);
|
|
309
|
+
|
|
310
|
+
if ($epConfigOApp.cl::get<bool>(lz::EpConfig::useDefaults)) {
|
|
311
|
+
cell $defaultSendEpConfig = $mdObj.cl::get<objRef>(md::MdObj::obj);
|
|
312
|
+
|
|
313
|
+
sendMsglib = $defaultSendEpConfig.cl::get<address>(lz::SendEpConfig::sendMsglibAddress);
|
|
314
|
+
|
|
315
|
+
sendMsglibConnection = $defaultSendEpConfig
|
|
316
|
+
.cl::get<address>(lz::SendEpConfig::sendMsglibConnectionAddress);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
;; Each send request is assigned a unique request ID, which is also used as the key into
|
|
320
|
+
;; the sendRequestQueue
|
|
321
|
+
int curRequestId = $storage.cl::get<uint64>(Channel::lastSendRequestId) + 1;
|
|
322
|
+
|
|
323
|
+
$lzSend = md::lzSend::fillRequestInfo($lzSend, curRequestId, sendMsglib, sendMsglibConnection);
|
|
324
|
+
|
|
325
|
+
cell sendRequestQueue = $storage.cl::get<cellRef>(Channel::sendRequestQueue);
|
|
326
|
+
(_, _, _, int exists) = DeterministicInsertionCircularQueue::get(sendRequestQueue, curRequestId);
|
|
327
|
+
ifnot (exists) {
|
|
328
|
+
;; submit to the msglib
|
|
329
|
+
setContractStorage(
|
|
330
|
+
$storage
|
|
331
|
+
.cl::set(Channel::lastSendRequestId, curRequestId)
|
|
332
|
+
.cl::set(
|
|
333
|
+
Channel::sendRequestQueue,
|
|
334
|
+
DeterministicInsertionCircularQueue::set(
|
|
335
|
+
sendRequestQueue,
|
|
336
|
+
curRequestId,
|
|
337
|
+
_buildSendRequestQueueEntry($lzSend),
|
|
338
|
+
SendRequestQueue::sending
|
|
339
|
+
)
|
|
340
|
+
)
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
actions~pushAction<call>(
|
|
344
|
+
sendMsglibConnection,
|
|
345
|
+
MsglibConnection::OP::MSGLIB_CONNECTION_SEND,
|
|
346
|
+
$lzSend
|
|
347
|
+
);
|
|
348
|
+
} else {
|
|
349
|
+
;; callback to the oApp with a failure and emit an event
|
|
350
|
+
actions~pushAction<event>(Channel::ERROR::sendQueueCongested, $lzSend);
|
|
351
|
+
actions~pushAction<call>(
|
|
352
|
+
$storage.cl::get<objRef>(Channel::path).cl::get<address>(lz::Path::srcOApp),
|
|
353
|
+
Layerzero::OP::CHANNEL_SEND_CALLBACK,
|
|
354
|
+
md::MdObj::New(
|
|
355
|
+
md::MessagingReceipt::New($lzSend, 0, 0, Channel::ERROR::sendQueueCongested),
|
|
356
|
+
getInitialStorage()
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return actions;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
;; in: msglib/handler.fc/msglibSend
|
|
365
|
+
;; in_md: MsglibSendCallback
|
|
366
|
+
;; out: OApp/handler.fc/sendCallback
|
|
367
|
+
tuple msglibSendCallback(cell $mdAddress) impure inline method_id {
|
|
368
|
+
(cell $storage, tuple actions) = preamble();
|
|
369
|
+
|
|
370
|
+
cell $mdMsglibSendCallback = $mdAddress.cl::get<objRef>(md::MdAddress::md);
|
|
371
|
+
|
|
372
|
+
int errorCode = $mdMsglibSendCallback.cl::get<uint8>(md::MsglibSendCallback::errorCode);
|
|
373
|
+
|
|
374
|
+
cell $lzSend = $mdMsglibSendCallback.cl::get<objRef>(md::MsglibSendCallback::lzSend);
|
|
375
|
+
cell sendRequestQueue = $storage.cl::get<cellRef>(Channel::sendRequestQueue);
|
|
376
|
+
|
|
377
|
+
int requestId = $lzSend.cl::get<uint64>(md::LzSend::sendRequestId);
|
|
378
|
+
|
|
379
|
+
;; Read the requestId from the sendRequestQueue to ensure this send request is genuine
|
|
380
|
+
;; and is not being double-executed
|
|
381
|
+
(_, cell contents, _, int exists) = DeterministicInsertionCircularQueue::get(sendRequestQueue, requestId);
|
|
382
|
+
if (exists) {
|
|
383
|
+
if (_readSendRequestQueueEntry(contents) == $lzSend.cl::hash()) {
|
|
384
|
+
$storage = $storage.cl::set(
|
|
385
|
+
Channel::sendRequestQueue,
|
|
386
|
+
DeterministicInsertionCircularQueue::delete(sendRequestQueue, requestId)
|
|
387
|
+
);
|
|
388
|
+
} else {
|
|
389
|
+
;; See below comment, this else case is logically the same as the below else block,
|
|
390
|
+
;; but needs to be split due to lack of short-circuiting boolean expressions in funC
|
|
391
|
+
return actions;
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
;; if the send request doesn't exist, there are two cases
|
|
395
|
+
;; 1. a legitimate request was frontrun by a force-abort
|
|
396
|
+
;; in this case, we can safely refund all the funds to the origin
|
|
397
|
+
;; 2. a malicious MITM attack by ULN
|
|
398
|
+
;; in this case, we can't refund the funds, but we can still emit an event
|
|
399
|
+
|
|
400
|
+
;; This technically silently reverts, by not processing any output actions,
|
|
401
|
+
;; thus providing a refund, instead of hard reverting
|
|
402
|
+
return actions;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
;; verify that cumulative fees quoted by the msglib <= the fee cap specified by the user/app
|
|
406
|
+
int zroQuote = $mdMsglibSendCallback.cl::get<coins>(md::MsglibSendCallback::zroFee);
|
|
407
|
+
int nativeQuote = $mdMsglibSendCallback.cl::get<coins>(md::MsglibSendCallback::nativeFee);
|
|
408
|
+
|
|
409
|
+
if ($lzSend.cl::get<coins>(md::LzSend::nativeFee) < nativeQuote) {
|
|
410
|
+
errorCode = Channel::ERROR::notEnoughNative;
|
|
411
|
+
}
|
|
412
|
+
if ($lzSend.cl::get<coins>(md::LzSend::zroFee) < zroQuote) {
|
|
413
|
+
errorCode = Channel::ERROR::notEnoughZroToken;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
;; Verify that the ZRO token credits in the Channel is sufficient to cover the
|
|
417
|
+
;; quoted ZRO cost of the message.
|
|
418
|
+
int zroBalance = $storage.cl::get<coins>(Channel::zroBalance);
|
|
419
|
+
if (zroBalance < zroQuote) {
|
|
420
|
+
errorCode = Channel::ERROR::notEnoughZroTokenBalance;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
cell $sendPath = $storage.cl::get<objRef>(Channel::path);
|
|
424
|
+
|
|
425
|
+
int packetNonce = 0;
|
|
426
|
+
int packetGuid = 0;
|
|
427
|
+
if (errorCode == Channel::NO_ERROR) {
|
|
428
|
+
;; Assign a nonce to the packet and calculate the resulting GUID
|
|
429
|
+
packetNonce = $storage.cl::get<uint64>(Channel::outboundNonce) + 1;
|
|
430
|
+
packetGuid = lz::Packet::calculateGuid($sendPath, packetNonce);
|
|
431
|
+
|
|
432
|
+
;; native payments
|
|
433
|
+
tuple payees = deserializePayees(
|
|
434
|
+
$mdMsglibSendCallback.cl::get<cellRef>(md::MsglibSendCallback::payees)
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
;; If the TON message does not contain sufficient value to perform the payments,
|
|
438
|
+
;; the transaction will revert and the send channel will eventually get blocked.
|
|
439
|
+
;; It is the responsibility of the OApp to assert sufficient gas + value to cover the
|
|
440
|
+
;; entire transaction and avoid this failure.
|
|
441
|
+
repeat (payees.tlen()) {
|
|
442
|
+
[int payeeAddress, int nativeAmount] = payees~tpopPayee();
|
|
443
|
+
actions~pushAction<payment>(payeeAddress, nativeAmount, 0);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
;; Due to asynchrony between the Msglib and the Channel, the nonce and guid
|
|
447
|
+
;; cannot be
|
|
448
|
+
cell encodedPacket = $mdMsglibSendCallback
|
|
449
|
+
.cl::get<cellRef>(md::MsglibSendCallback::packetEncoded);
|
|
450
|
+
|
|
451
|
+
int nonceByteOffset = $mdMsglibSendCallback
|
|
452
|
+
.cl::get<uint16>(md::MsglibSendCallback::nonceByteOffset);
|
|
453
|
+
|
|
454
|
+
int nonceBytes = $mdMsglibSendCallback
|
|
455
|
+
.cl::get<uint8>(md::MsglibSendCallback::nonceBytes);
|
|
456
|
+
|
|
457
|
+
int guidByteOffset = $mdMsglibSendCallback
|
|
458
|
+
.cl::get<uint16>(md::MsglibSendCallback::guidByteOffset);
|
|
459
|
+
|
|
460
|
+
int guidBytes = $mdMsglibSendCallback.cl::get<uint8>(md::MsglibSendCallback::guidBytes);
|
|
461
|
+
|
|
462
|
+
cell completedEncodedPacket = null();
|
|
463
|
+
|
|
464
|
+
if (guidByteOffset > nonceByteOffset) {
|
|
465
|
+
completedEncodedPacket = encodedPacket
|
|
466
|
+
.lz::Packet::replaceTwoFieldsAtOffsets(
|
|
467
|
+
packetNonce,
|
|
468
|
+
nonceByteOffset,
|
|
469
|
+
nonceBytes,
|
|
470
|
+
packetGuid,
|
|
471
|
+
guidByteOffset,
|
|
472
|
+
guidBytes
|
|
473
|
+
);
|
|
474
|
+
} else {
|
|
475
|
+
completedEncodedPacket = encodedPacket
|
|
476
|
+
.lz::Packet::replaceTwoFieldsAtOffsets(
|
|
477
|
+
packetGuid,
|
|
478
|
+
guidByteOffset,
|
|
479
|
+
guidBytes,
|
|
480
|
+
packetNonce,
|
|
481
|
+
nonceByteOffset,
|
|
482
|
+
nonceBytes
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
actions~pushAction<event>(
|
|
487
|
+
Channel::event::PACKET_SENT,
|
|
488
|
+
md::PacketSent::New(
|
|
489
|
+
nativeQuote,
|
|
490
|
+
zroQuote,
|
|
491
|
+
$lzSend.cl::get<objRef>(md::LzSend::extraOptions),
|
|
492
|
+
$lzSend.cl::get<objRef>(md::LzSend::enforcedOptions),
|
|
493
|
+
completedEncodedPacket,
|
|
494
|
+
packetNonce,
|
|
495
|
+
$mdAddress.cl::get<address>(md::MdAddress::address), ;; msglib manager address
|
|
496
|
+
$mdMsglibSendCallback.cl::get<objRef>(md::MsglibSendCallback::msglibSendEvents)
|
|
497
|
+
)
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
$storage = $storage
|
|
501
|
+
.cl::set(Channel::zroBalance, zroBalance - zroQuote)
|
|
502
|
+
.cl::set(Channel::outboundNonce, packetNonce);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
;; If the quote was unsuccessful, delete the hash from storage to prevent hol blocking
|
|
506
|
+
;; If the quote was successful, additionally update the ZRO balance and outbound nonce
|
|
507
|
+
setContractStorage($storage);
|
|
508
|
+
|
|
509
|
+
actions~pushAction<call>(
|
|
510
|
+
$sendPath.cl::get<address>(lz::Path::srcOApp),
|
|
511
|
+
Layerzero::OP::CHANNEL_SEND_CALLBACK,
|
|
512
|
+
md::MdObj::New(
|
|
513
|
+
md::MessagingReceipt::New(
|
|
514
|
+
$lzSend.cl::set(
|
|
515
|
+
md::LzSend::packet,
|
|
516
|
+
$lzSend
|
|
517
|
+
.cl::get<objRef>(md::LzSend::packet)
|
|
518
|
+
.cl::set(lz::Packet::nonce, packetNonce)
|
|
519
|
+
.cl::set(lz::Packet::guid, packetGuid)
|
|
520
|
+
),
|
|
521
|
+
nativeQuote,
|
|
522
|
+
zroQuote,
|
|
523
|
+
errorCode
|
|
524
|
+
),
|
|
525
|
+
getInitialStorage()
|
|
526
|
+
)
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
return actions;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
;;; ==========================================
|
|
533
|
+
;; Receive flow
|
|
534
|
+
;; @in endpoint/handler.fc/verify
|
|
535
|
+
;; @in_md ExtendedMd(msglibConnectionAddress, defaultEpConfig, verify)
|
|
536
|
+
;; @out packet_receive/handler.fc/verify
|
|
537
|
+
;; @out_md ExtendedMd(msglib_addr, _, verify)
|
|
538
|
+
;; @out controller/handler.fc/emit_event
|
|
539
|
+
tuple channelCommitPacket(cell $mdExtended) impure inline method_id {
|
|
540
|
+
(cell $storage, tuple actions) = preamble();
|
|
541
|
+
|
|
542
|
+
cell $packet = $mdExtended.cl::get<objRef>(md::ExtendedMd::md);
|
|
543
|
+
;; assert the size of the incoming packet
|
|
544
|
+
lz::Packet::assertValidReceiveMessage($packet);
|
|
545
|
+
|
|
546
|
+
cell $epConfigOApp = $storage.cl::get<objRef>(Channel::epConfigOApp);
|
|
547
|
+
int receiveMsglibConnection = $epConfigOApp.cl::get<address>(
|
|
548
|
+
lz::EpConfig::receiveMsglibConnection
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
int useDefaults = $epConfigOApp.cl::get<bool>(lz::EpConfig::useDefaults);
|
|
552
|
+
|
|
553
|
+
if (useDefaults) {
|
|
554
|
+
cell $defaultConfig = $mdExtended.cl::get<objRef>(md::MdObj::obj);
|
|
555
|
+
receiveMsglibConnection = $defaultConfig
|
|
556
|
+
.cl::get<address>(lz::ReceiveEpConfig::receiveMsglibConnectionAddress);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
int callerMsglibConnectionAddress = $mdExtended
|
|
560
|
+
.cl::get<address>(md::ExtendedMd::forwardingAddress);
|
|
561
|
+
|
|
562
|
+
if (receiveMsglibConnection != callerMsglibConnectionAddress) {
|
|
563
|
+
;; grossly inefficient, but this will (almost) never happen
|
|
564
|
+
;; so we can optimize the happy path by isolating this logic into this block
|
|
565
|
+
cell $defaultConfig = $mdExtended.cl::get<objRef>(md::MdObj::obj);
|
|
566
|
+
int timeoutReceiveMsglibConnection = useDefaults
|
|
567
|
+
? $defaultConfig
|
|
568
|
+
.cl::get<address>(lz::ReceiveEpConfig::timeoutReceiveMsglibConnectionAddress)
|
|
569
|
+
: $epConfigOApp.cl::get<address>(lz::EpConfig::timeoutReceiveMsglibConnection);
|
|
570
|
+
|
|
571
|
+
int expiry = useDefaults
|
|
572
|
+
? $defaultConfig.cl::get<uint64>(lz::ReceiveEpConfig::expiry)
|
|
573
|
+
: $epConfigOApp.cl::get<uint64>(lz::EpConfig::timeoutReceiveMsglibExpiry);
|
|
574
|
+
|
|
575
|
+
if ((timeoutReceiveMsglibConnection != callerMsglibConnectionAddress) | (expiry < now())) {
|
|
576
|
+
throw(Channel::ERROR::onlyApprovedReceiveMsglib);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
int incomingNonce = $packet.cl::get<uint64>(lz::Packet::nonce);
|
|
581
|
+
cell $commitPOOO = $storage.cl::get<objRef>(Channel::commitPOOO);
|
|
582
|
+
|
|
583
|
+
(
|
|
584
|
+
int isCommittable,
|
|
585
|
+
_
|
|
586
|
+
) = _nonceCommittable(incomingNonce);
|
|
587
|
+
|
|
588
|
+
if (isCommittable) {
|
|
589
|
+
setContractStorage(
|
|
590
|
+
$storage
|
|
591
|
+
.cl::set(Channel::commitPOOO, POOO::set($commitPOOO, incomingNonce))
|
|
592
|
+
.cl::set(Channel::executionQueue,
|
|
593
|
+
DeterministicInsertionCircularQueue::set(
|
|
594
|
+
$storage.cl::get<cellRef>(Channel::executionQueue),
|
|
595
|
+
incomingNonce,
|
|
596
|
+
$packet,
|
|
597
|
+
ExecutionQueue::committed
|
|
598
|
+
)
|
|
599
|
+
)
|
|
600
|
+
);
|
|
601
|
+
actions~pushAction<event>(Channel::event::PACKET_COMMITTED, $packet);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (incomingNonce <= POOO::maxSettableBit($storage.cl::get<objRef>(Channel::executePOOO))) {
|
|
605
|
+
;; Cannot respond back to msglib if the packet is not currently committable but
|
|
606
|
+
;; will be committable in the future
|
|
607
|
+
;; Caveat: if the packet is currently executing, we treat it as uncommittable.
|
|
608
|
+
;; There exists a race condition where a uncommitted re-committable packet
|
|
609
|
+
;; can be marked as committed. If the packet needs to be re-committed for a good reason
|
|
610
|
+
;; (e.g., malicious DVN), the OApp owner must first nilify the packet
|
|
611
|
+
|
|
612
|
+
actions~pushAction<call>(
|
|
613
|
+
callerMsglibConnectionAddress,
|
|
614
|
+
MsglibConnection::OP::MSGLIB_CONNECTION_COMMIT_PACKET_CALLBACK,
|
|
615
|
+
md::ChannelNonceInfo::New(
|
|
616
|
+
incomingNonce,
|
|
617
|
+
$storage.cl::get<objRef>(Channel::executePOOO).cl::get<uint64>(POOO::nextEmpty)
|
|
618
|
+
)
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
return actions;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
;;; ==========================================
|
|
627
|
+
;; Execution step 1
|
|
628
|
+
;; @in_opcode Channel::OP::LZ_RECEIVE_PREPARE
|
|
629
|
+
;; @in_from (external in) permissionless
|
|
630
|
+
;; @in_md nonce
|
|
631
|
+
;; @out_opcode Layerzero::OP::LZ_RECEIVE_PREPARE
|
|
632
|
+
;; @out_to srcOApp
|
|
633
|
+
;; @out_md ExtendedMd(md=packetId, obj=channel_init_state, forwarding_addr=NULLADDRESS)
|
|
634
|
+
;; @permissions: permissonless
|
|
635
|
+
tuple lzReceivePrepare(cell $lzReceivePrepareMd) impure inline method_id {
|
|
636
|
+
(cell $storage, tuple actions) = preamble();
|
|
637
|
+
int nonce = $lzReceivePrepareMd.cl::get<uint64>(md::LzReceivePrepare::nonce);
|
|
638
|
+
int nanotons = $lzReceivePrepareMd.cl::get<coins>(md::LzReceivePrepare::nanotons);
|
|
639
|
+
|
|
640
|
+
;; extract oApp from path
|
|
641
|
+
actions~pushAction<dispatch>(
|
|
642
|
+
$storage.cl::get<objRef>(Channel::path).cl::get<uint256>(lz::Path::srcOApp),
|
|
643
|
+
Layerzero::OP::LZ_RECEIVE_PREPARE,
|
|
644
|
+
;; Throws if the Packet is not executable
|
|
645
|
+
_getExecutablePacket(nonce),
|
|
646
|
+
nanotons
|
|
647
|
+
);
|
|
648
|
+
|
|
649
|
+
return actions;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
;; @in_opcode Channel::OP::LZ_RECEIVE_LOCK
|
|
653
|
+
;; @in_from oApp
|
|
654
|
+
;; @in_md nonce
|
|
655
|
+
;; @out_opcode Layerzero::OP::LZ_RECEIVE_EXECUTE
|
|
656
|
+
;; @out_to oApp
|
|
657
|
+
;; @out_md ExtendedMd(md=Packet, obj=channel_init_state, forwarding_addr=NULLADDRESS)
|
|
658
|
+
;; @permissions: only oApp
|
|
659
|
+
tuple lzReceiveLock(cell $nonceMd) impure inline method_id {
|
|
660
|
+
(cell $storage, tuple actions) = preamble();
|
|
661
|
+
|
|
662
|
+
int incomingNonce = $nonceMd.cl::get<uint64>(md::Nonce::nonce);
|
|
663
|
+
|
|
664
|
+
throw_if(Channel::ERROR::invalidNonce, incomingNonce <= 0);
|
|
665
|
+
cell executionQueue = $storage.cl::get<cellRef>(Channel::executionQueue);
|
|
666
|
+
|
|
667
|
+
(int actualKey, cell $packet, int status, _) = DeterministicInsertionCircularQueue::get(
|
|
668
|
+
executionQueue,
|
|
669
|
+
incomingNonce
|
|
670
|
+
);
|
|
671
|
+
|
|
672
|
+
int firstUncommittedNonce = getContractStorage()
|
|
673
|
+
.cl::get<objRef>(Channel::commitPOOO)
|
|
674
|
+
.cl::get<uint64>(POOO::nextEmpty);
|
|
675
|
+
|
|
676
|
+
;; executable if present and all preceding nonces are committed, executing, or executed
|
|
677
|
+
if (
|
|
678
|
+
(actualKey == incomingNonce)
|
|
679
|
+
& (status == ExecutionQueue::committed)
|
|
680
|
+
& (incomingNonce < firstUncommittedNonce)
|
|
681
|
+
) {
|
|
682
|
+
;; set state to executing
|
|
683
|
+
setContractStorage(
|
|
684
|
+
$storage.cl::set(
|
|
685
|
+
Channel::executionQueue,
|
|
686
|
+
DeterministicInsertionCircularQueue::set(
|
|
687
|
+
executionQueue,
|
|
688
|
+
incomingNonce,
|
|
689
|
+
$packet,
|
|
690
|
+
ExecutionQueue::executing
|
|
691
|
+
)
|
|
692
|
+
)
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
actions~pushAction<call>(
|
|
696
|
+
$storage.cl::get<objRef>(Channel::path).cl::get<uint256>(lz::Path::srcOApp),
|
|
697
|
+
Layerzero::OP::LZ_RECEIVE_EXECUTE,
|
|
698
|
+
md::MdObj::New($packet, getInitialStorage())
|
|
699
|
+
);
|
|
700
|
+
} else {
|
|
701
|
+
actions~pushAction<event>(
|
|
702
|
+
Channel::event::NOT_EXECUTABLE,
|
|
703
|
+
md::PacketId::New($storage.cl::get<objRef>(Channel::path), incomingNonce)
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return actions;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
;; @in_opcode Channel::OP::LZ_RECEIVE_EXECUTE_CALLBACK
|
|
711
|
+
;; @in_from oApp
|
|
712
|
+
;; @in_md LzReceiveStatus
|
|
713
|
+
;; @out_opcode OP::PACKET_RECEIVE_DESTROYED_CALLBACK
|
|
714
|
+
;; @out_to oApp
|
|
715
|
+
;; @out_md ExtendedMd(md=packetId, obj=pr_init_state, forwarding_addr=address_std_hashpart_null())
|
|
716
|
+
;; @failure => unlock the Packet
|
|
717
|
+
;; @success => destroy the Packet and refund rent
|
|
718
|
+
;; @permissions: only oApp
|
|
719
|
+
tuple lzReceiveExecuteCallback(cell $lzReceiveStatus) impure inline method_id {
|
|
720
|
+
(cell $storage, tuple actions) = preamble();
|
|
721
|
+
|
|
722
|
+
int packetNonce = $lzReceiveStatus.cl::get<uint64>(md::LzReceiveStatus::nonce);
|
|
723
|
+
cell executionQueue = $storage.cl::get<cellRef>(Channel::executionQueue);
|
|
724
|
+
|
|
725
|
+
(int actualKey, cell $packet, int status, _) = DeterministicInsertionCircularQueue::get(
|
|
726
|
+
executionQueue,
|
|
727
|
+
packetNonce
|
|
728
|
+
);
|
|
729
|
+
|
|
730
|
+
throw_unless(
|
|
731
|
+
Channel::ERROR::notExecuting,
|
|
732
|
+
(actualKey == packetNonce) & (status == ExecutionQueue::executing)
|
|
733
|
+
);
|
|
734
|
+
|
|
735
|
+
;; check for success/failure
|
|
736
|
+
if ($lzReceiveStatus.cl::get<bool>(md::LzReceiveStatus::success)) {
|
|
737
|
+
executionQueue = DeterministicInsertionCircularQueue::delete(executionQueue, packetNonce);
|
|
738
|
+
|
|
739
|
+
$storage = $storage.cl::set(
|
|
740
|
+
Channel::executePOOO,
|
|
741
|
+
POOO::set($storage.cl::get<objRef>(Channel::executePOOO), packetNonce)
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
;; emit Packet in the manager
|
|
745
|
+
actions~pushAction<event>(
|
|
746
|
+
Channel::event::DELIVERED,
|
|
747
|
+
md::PacketId::New($storage.cl::get<objRef>(Channel::path), packetNonce)
|
|
748
|
+
);
|
|
749
|
+
} else {
|
|
750
|
+
executionQueue = DeterministicInsertionCircularQueue::set(
|
|
751
|
+
executionQueue,
|
|
752
|
+
packetNonce,
|
|
753
|
+
$packet, ;; same packet object that we extracted from the queue
|
|
754
|
+
ExecutionQueue::committed
|
|
755
|
+
);
|
|
756
|
+
|
|
757
|
+
;; emit Packet so we know its unlocked
|
|
758
|
+
actions~pushAction<event>(
|
|
759
|
+
Channel::event::LZ_RECEIVE_ALERT,
|
|
760
|
+
md::LzReceiveStatus::NewFull(
|
|
761
|
+
false,
|
|
762
|
+
packetNonce,
|
|
763
|
+
$lzReceiveStatus.cl::get<coins>(md::LzReceiveStatus::value),
|
|
764
|
+
$lzReceiveStatus.cl::get<cellRef>(md::LzReceiveStatus::extraData),
|
|
765
|
+
$lzReceiveStatus.cl::get<cellRef>(md::LzReceiveStatus::reason),
|
|
766
|
+
getOrigin(),
|
|
767
|
+
$packet,
|
|
768
|
+
ExecutionStatus::executable
|
|
769
|
+
)
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
setContractStorage($storage.cl::set(Channel::executionQueue, executionQueue));
|
|
774
|
+
|
|
775
|
+
return actions;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
;;; ====================== Management Helper ===================================
|
|
779
|
+
() _commitFakePacket(cell $storage, int nonce, cell $receivePath) impure inline method_id {
|
|
780
|
+
cell $mockPacket = lz::Packet::New($receivePath, empty_cell(), nonce);
|
|
781
|
+
|
|
782
|
+
;; Because this is not originating from the endpoint, we dont have the defaults
|
|
783
|
+
;; Actual defaults and the msglib address arent required because the call is direct from the OApp
|
|
784
|
+
cell $mockEpConfigDefaults = lz::ReceiveEpConfig::New(
|
|
785
|
+
0xdeadbeef, ;; any non-null dummy value for the receive msglib connection address
|
|
786
|
+
NULLADDRESS, ;; timeout never has to be used for burn
|
|
787
|
+
0 ;; as above, timeout never has to be used for burn
|
|
788
|
+
);
|
|
789
|
+
cell $epConfigOApp = $storage.cl::get<objRef>(Channel::epConfigOApp);
|
|
790
|
+
|
|
791
|
+
;; Step 1: Commit the 'mockPacket'
|
|
792
|
+
;; This is safe because we are going to do the following steps (2 and 3) atomically.
|
|
793
|
+
;; channelCommitPacket will not revert if the packet is not committed, but lzReceiveLock will.
|
|
794
|
+
;; Basically lying to channelCommitPacket to say the "correct" msglib is committing
|
|
795
|
+
channelCommitPacket(
|
|
796
|
+
md::ExtendedMd::New(
|
|
797
|
+
$mockPacket,
|
|
798
|
+
$mockEpConfigDefaults, ;; this is completely ignored if useDefaults is false
|
|
799
|
+
$epConfigOApp.cl::get<bool>(lz::EpConfig::useDefaults)
|
|
800
|
+
? $mockEpConfigDefaults.cl::get<address>(lz::EpConfig::receiveMsglibConnection)
|
|
801
|
+
: $epConfigOApp.cl::get<address>(lz::EpConfig::receiveMsglibConnection)
|
|
802
|
+
)
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
;; @permissions only-oApp
|
|
807
|
+
tuple nilify(cell $packetId) impure inline method_id {
|
|
808
|
+
(cell $storage, tuple actions) = preamble();
|
|
809
|
+
|
|
810
|
+
cell $receivePath = $storage.cl::get<objRef>(Channel::path).lz::Path::optimizedReverse();
|
|
811
|
+
_assertEqualPaths($receivePath, $packetId.cl::get<objRef>(md::PacketId::path));
|
|
812
|
+
|
|
813
|
+
int incomingNonce = $packetId.cl::get<uint64>(md::PacketId::nonce);
|
|
814
|
+
_assertNonceCommittable(incomingNonce);
|
|
815
|
+
|
|
816
|
+
(_, cell $previousPacket) = _nonceCommittable(incomingNonce);
|
|
817
|
+
|
|
818
|
+
_commitFakePacket($storage, incomingNonce, $receivePath);
|
|
819
|
+
|
|
820
|
+
setContractStorage(
|
|
821
|
+
getContractStorage().cl::set(
|
|
822
|
+
Channel::executionQueue,
|
|
823
|
+
DeterministicInsertionCircularQueue::delete(
|
|
824
|
+
$storage.cl::get<cellRef>(Channel::executionQueue),
|
|
825
|
+
incomingNonce
|
|
826
|
+
)
|
|
827
|
+
)
|
|
828
|
+
);
|
|
829
|
+
|
|
830
|
+
if ($previousPacket.is_null()) {
|
|
831
|
+
$previousPacket = lz::Packet::New($receivePath, empty_cell(), incomingNonce);
|
|
832
|
+
}
|
|
833
|
+
actions~pushAction<event>(Channel::event::PACKET_NILIFIED, $previousPacket);
|
|
834
|
+
|
|
835
|
+
actions~pushAction<call>(
|
|
836
|
+
$receivePath.cl::get<uint256>(lz::Path::dstOApp),
|
|
837
|
+
Layerzero::OP::NILIFY_CALLBACK,
|
|
838
|
+
md::MdObj::New($packetId, getInitialStorage())
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
return actions;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
tuple burn(cell $packetId) impure inline method_id {
|
|
845
|
+
(cell $storage, tuple actions) = preamble();
|
|
846
|
+
|
|
847
|
+
;; reverse the path because this is from a receive perspective
|
|
848
|
+
cell $receivePath = lz::Path::reverse($storage.cl::get<objRef>(Channel::path));
|
|
849
|
+
_assertEqualPaths($receivePath, $packetId.cl::get<objRef>(md::PacketId::path));
|
|
850
|
+
|
|
851
|
+
int nonce = $packetId.cl::get<uint64>(md::PacketId::nonce);
|
|
852
|
+
|
|
853
|
+
cell $nonceMd = md::Nonce::New(nonce);
|
|
854
|
+
|
|
855
|
+
(_, cell $previousPacket) = _nonceCommittable(nonce);
|
|
856
|
+
|
|
857
|
+
;; Step 1: Commit a 'mockPacket' to be used when we 'burn' this nonce
|
|
858
|
+
_commitFakePacket($storage, nonce, $receivePath);
|
|
859
|
+
|
|
860
|
+
;; Step 2: Put the packet into 'executing'
|
|
861
|
+
lzReceiveLock($nonceMd);
|
|
862
|
+
;; Step 3: Mock the lzReceiveExecuteCallback, which marks/flags that given nonce as used and 'executed'
|
|
863
|
+
lzReceiveExecuteCallback(md::LzReceiveStatus::New(true, nonce));
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
if ($previousPacket.is_null()) {
|
|
867
|
+
$previousPacket = lz::Packet::New($receivePath, empty_cell(), nonce);
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
;; Emit an event so we are able to observe offchain that this nonce has been 'burned'
|
|
871
|
+
actions~pushAction<event>(
|
|
872
|
+
Channel::event::PACKET_BURNED,
|
|
873
|
+
$previousPacket
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
cell $packetId = md::PacketId::New($receivePath, nonce);
|
|
877
|
+
actions~pushAction<call>(
|
|
878
|
+
$receivePath.cl::get<uint256>(lz::Path::dstOApp),
|
|
879
|
+
Layerzero::OP::BURN_CALLBACK,
|
|
880
|
+
md::MdObj::New($packetId, getInitialStorage())
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
return actions;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
;;; ==========================================
|
|
887
|
+
;; ZRO management
|
|
888
|
+
;; only controller
|
|
889
|
+
tuple depositZro(cell $coinsAmount) impure inline method_id {
|
|
890
|
+
(cell $storage, tuple actions) = preamble();
|
|
891
|
+
|
|
892
|
+
setContractStorage(
|
|
893
|
+
$storage.cl::set(
|
|
894
|
+
Channel::zroBalance,
|
|
895
|
+
$storage.cl::get<coins>(Channel::zroBalance)
|
|
896
|
+
+ $coinsAmount.cl::get<coins>(md::CoinsAmount::amount)
|
|
897
|
+
)
|
|
898
|
+
);
|
|
899
|
+
|
|
900
|
+
actions~pushAction<event>(Channel::event::ZRO_DEPOSITED, $coinsAmount);
|
|
901
|
+
|
|
902
|
+
return actions;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
;; Attempt to abort a send request. Check if hash still present, if present delete and send
|
|
906
|
+
;; @in: oApp
|
|
907
|
+
;; @in_opcode Channel::OP::FORCE_ABORT
|
|
908
|
+
;; @in_md lzSend
|
|
909
|
+
;; @out_opcode
|
|
910
|
+
;; @out_to oApp
|
|
911
|
+
;; @out_md lzSend
|
|
912
|
+
;; @permissions: only oApp
|
|
913
|
+
tuple forceAbort(cell $lzSend) impure inline method_id {
|
|
914
|
+
(cell $storage, tuple actions) = preamble();
|
|
915
|
+
|
|
916
|
+
cell $path = $storage.cl::get<objRef>(Channel::path);
|
|
917
|
+
_assertEqualPaths(
|
|
918
|
+
$path,
|
|
919
|
+
$lzSend
|
|
920
|
+
.cl::get<objRef>(md::LzSend::packet)
|
|
921
|
+
.cl::get<objRef>(lz::Packet::path)
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
int requestId = $lzSend.cl::get<uint64>(md::LzSend::sendRequestId);
|
|
925
|
+
|
|
926
|
+
cell sendRequestQueue = $storage.cl::get<cellRef>(Channel::sendRequestQueue);
|
|
927
|
+
|
|
928
|
+
(_, cell request, int status, _) = DeterministicInsertionCircularQueue::get(sendRequestQueue, requestId);
|
|
929
|
+
|
|
930
|
+
throw_if(
|
|
931
|
+
Channel::ERROR::cannotAbortSend,
|
|
932
|
+
(status != SendRequestQueue::sending) | (_readSendRequestQueueEntry(request) != $lzSend.cl::hash())
|
|
933
|
+
);
|
|
934
|
+
|
|
935
|
+
;; delete the reservation and update the storage
|
|
936
|
+
setContractStorage(
|
|
937
|
+
$storage.cl::set(
|
|
938
|
+
Channel::sendRequestQueue,
|
|
939
|
+
DeterministicInsertionCircularQueue::delete(sendRequestQueue, requestId)
|
|
940
|
+
)
|
|
941
|
+
);
|
|
942
|
+
|
|
943
|
+
actions~pushAction<call>(
|
|
944
|
+
$path.cl::get<uint256>(lz::Path::srcOApp),
|
|
945
|
+
Layerzero::OP::CHANNEL_SEND_CALLBACK,
|
|
946
|
+
md::MdObj::New(
|
|
947
|
+
md::MessagingReceipt::New($lzSend, 0, 0, Channel::ERROR::sendAborted),
|
|
948
|
+
getInitialStorage()
|
|
949
|
+
)
|
|
950
|
+
);
|
|
951
|
+
|
|
952
|
+
return actions;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
;; Send the current state of the channel to the MsglibConnection
|
|
956
|
+
;; @in: permissionless
|
|
957
|
+
;; @in_opcode Channel::OP::MSGLIB_CONNECTION_SYNC_CHANNEL_STATE
|
|
958
|
+
;; @in_md mdAddress ( MsglibConnectionAddress, Path )
|
|
959
|
+
tuple syncMsglibConnection(cell $mdAddress) impure inline method_id {
|
|
960
|
+
(cell $storage, tuple actions) = preamble();
|
|
961
|
+
|
|
962
|
+
actions~pushAction<call>(
|
|
963
|
+
$mdAddress.cl::get<address>(md::MdAddress::address), ;; msglibConnectionAddress
|
|
964
|
+
MsglibConnection::OP::MSGLIB_CONNECTION_SYNC_CHANNEL_STATE,
|
|
965
|
+
md::MdObj::New(
|
|
966
|
+
md::ChannelNonceInfo::New(
|
|
967
|
+
$storage
|
|
968
|
+
.cl::get<objRef>(Channel::commitPOOO)
|
|
969
|
+
.cl::get<uint64>(POOO::nextEmpty),
|
|
970
|
+
$storage
|
|
971
|
+
.cl::get<objRef>(Channel::executePOOO)
|
|
972
|
+
.cl::get<uint64>(POOO::nextEmpty)
|
|
973
|
+
),
|
|
974
|
+
getInitialStorage()
|
|
975
|
+
)
|
|
976
|
+
);
|
|
977
|
+
|
|
978
|
+
return actions;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
tuple notifyPacketExecuted(cell $mdAddress) impure inline method_id {
|
|
982
|
+
(cell $storage, tuple actions) = preamble();
|
|
983
|
+
|
|
984
|
+
cell $nonceMd = $mdAddress.cl::get<objRef>(md::MdAddress::md);
|
|
985
|
+
|
|
986
|
+
int executionStatus = _viewExecutionStatus($nonceMd.cl::get<uint64>(md::Nonce::nonce));
|
|
987
|
+
|
|
988
|
+
if (executionStatus != ExecutionStatus::executed) {
|
|
989
|
+
return actions;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
actions~pushAction<call>(
|
|
993
|
+
$mdAddress.cl::get<address>(md::MdAddress::address),
|
|
994
|
+
MsglibConnection::OP::MSGLIB_CONNECTION_COMMIT_PACKET_CALLBACK,
|
|
995
|
+
md::ChannelNonceInfo::New(
|
|
996
|
+
$nonceMd.cl::get<uint64>(md::Nonce::nonce),
|
|
997
|
+
$storage.cl::get<objRef>(Channel::executePOOO).cl::get<uint64>(POOO::nextEmpty)
|
|
998
|
+
)
|
|
999
|
+
);
|
|
1000
|
+
return actions;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
tuple emitLzReceiveAlert(cell $lzReceiveStatus) impure inline method_id {
|
|
1004
|
+
(cell $storage, tuple actions) = preamble();
|
|
1005
|
+
int nonce = $lzReceiveStatus.cl::get<uint64>(md::LzReceiveStatus::nonce);
|
|
1006
|
+
throw_if(Channel::ERROR::invalidNonce, nonce == 0);
|
|
1007
|
+
int executionStatus = _viewExecutionStatus(nonce);
|
|
1008
|
+
(int actualNonce, cell $packet, _, int exists) = DeterministicInsertionCircularQueue::get(
|
|
1009
|
+
$storage.cl::get<cellRef>(Channel::executionQueue),
|
|
1010
|
+
nonce
|
|
1011
|
+
);
|
|
1012
|
+
|
|
1013
|
+
throw_unless(
|
|
1014
|
+
Channel::ERROR::invalidNonce,
|
|
1015
|
+
(actualNonce == nonce) & (exists)
|
|
1016
|
+
);
|
|
1017
|
+
|
|
1018
|
+
actions~pushAction<event>(
|
|
1019
|
+
Channel::event::LZ_RECEIVE_ALERT,
|
|
1020
|
+
md::LzReceiveStatus::NewFull(
|
|
1021
|
+
$lzReceiveStatus.cl::get<bool>(md::LzReceiveStatus::success),
|
|
1022
|
+
nonce,
|
|
1023
|
+
$lzReceiveStatus.cl::get<coins>(md::LzReceiveStatus::value),
|
|
1024
|
+
$lzReceiveStatus.cl::get<cellRef>(md::LzReceiveStatus::extraData),
|
|
1025
|
+
$lzReceiveStatus.cl::get<cellRef>(md::LzReceiveStatus::reason),
|
|
1026
|
+
getCaller(),
|
|
1027
|
+
$packet,
|
|
1028
|
+
executionStatus
|
|
1029
|
+
)
|
|
1030
|
+
);
|
|
1031
|
+
return actions;
|
|
1032
|
+
}
|