Skip to content

Commit 6755541

Browse files
OffRamp commit wrappers and tests (#83)
* add handler for SetOCR3BaseConfig * add transmit calls on the OffRamp * add ccip/OffRamp.ts tes * check that offRamp handles setOCR3Base message * fix broken ccipRouter test * handle setOCR3Config on functino on contract * refactor: move examples under test/ folder on contracts * fmt * fmt * use real feeQuoter * fmt * fix compilation bugs * fix compilation error * fmt * set commit and exec configs on offramp * init offramp ts wrappers * remove RMN and get commit message to be handled * refactor: assertLog, test offRamp emits CCIPCommitReportAccepted * fix merge error * define commit test with message * add wrappers to set sourceChainConfig * add updateSourceChainConfig, fix errors, tests pass * format * use strincCrc32 * use stringCrc32 on ocr logs * delete unused feeQuoter mock * Update contracts/wrappers/ccip/Logs.ts Co-authored-by: Copilot <[email protected]> * test commit report fails when chain not enabled * fix deserialize merkleRoots * fmt * use CommitReport instead of Cell<CommitReport> * fmt * remove unnecesary workchain attribute on init * remove noop line from previous debugging * rename LogTypes to CombinedLogTypes * fmt * test commit report with two roots * fmt * fix wrong path to utils * fix broken path in offramp tests --------- Co-authored-by: Copilot <[email protected]>
1 parent 020e0fa commit 6755541

File tree

13 files changed

+960
-278
lines changed

13 files changed

+960
-278
lines changed

contracts/contracts/ccip/offramp.tolk

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Storage {
1212
deployer: cell; // Deployable compiled code
1313
merkleRootCode: cell; // make sure to use a library cell offchain to save space
1414
feeQuoter: address;
15-
ocr3Base: OCR3Base
15+
ocr3Base: Cell<OCR3Base>
1616

1717
// static config
1818
chainSelector: uint64;
@@ -26,7 +26,7 @@ struct Storage {
2626
}
2727

2828
struct SourceChainConfig {
29-
router: address;
29+
router: CrossChainAddress;
3030
isEnabled: bool;
3131
minSeqNr: uint64;
3232
isRMNVerificationDisabled: bool;
@@ -60,13 +60,12 @@ struct ExecutionStateChanged {
6060
state: uint8;
6161
}
6262

63-
// TODO: use sha256("CommitReportAccepted")
64-
const CCIP_COMMIT_REPORT_ACCEPTED_TOPIC: int = 0x99; // for easier indexing
63+
// crc32("CCIPCommitReportAccepted")
64+
const CCIP_COMMIT_REPORT_ACCEPTED_TOPIC: int = stringCrc32("CCIPCommitReportAccepted");
6565

6666
struct CommitReportAccepted {
6767
priceUpdates: Cell<PriceUpdates>?;
68-
blessedMerkleRoots: cell;
69-
unblessedMerkleRoots: cell;
68+
merkleRoots: cell // vec<MerkleRoots>
7069
}
7170

7271
struct SkippedReportExecution {
@@ -84,17 +83,15 @@ struct ExecutionReport {
8483
// Matches the EVM struct
8584
struct CommitReport {
8685
priceUpdates: Cell<PriceUpdates>?; // Price updates for the fee_quoter
87-
blessedMerkleRoots: cell; // vec<MerkleRoot> Merkle roots that have been blessed by RMN
88-
unblessedMerkleRoots: cell; // vec<MerkleRoot> Merkle roots that don't require RMN blessing
89-
rmnSignatures: cell; //vec<bytes32> The signatures for the blessed merkle roots
86+
merkleRoots: cell; // vec<MerkleRoot> Merkle roots
9087
}
9188

9289
struct (0x00000001) Commit {
9390
queryId: uint64;
9491
// TODO: could just store as one slice since context is fixed size
9592
reportContext: ReportContext;
9693
report: CommitReport;
97-
signatures: cell;
94+
signatures: cell; //vec<SignatureEd25519>
9895
}
9996

10097
struct (0x00000002) Execute {
@@ -104,14 +101,23 @@ struct (0x00000002) Execute {
104101
report: ExecutionReport;
105102
}
106103

107-
type Msg = Commit | Execute | OCR3Base_SetOCR3Config;
104+
struct (0x00000003) UpdateSourceChainConfig {
105+
queryId: uint64;
106+
sourceChainSelector: uint64;
107+
config: SourceChainConfig
108+
}
109+
110+
type Msg = Commit | Execute | UpdateSourceChainConfig | OCR3Base_SetOCR3Config;
108111

109112
fun onInternalMessage(in:InMessage) {
110113
val msg = lazy Msg.fromSlice(in.body);
111114
match (msg) {
112-
Commit => { commit(msg, in.senderAddress) }
115+
Commit => {
116+
commit(msg, in.senderAddress)
117+
}
113118
Execute => { _execute(msg, in.senderAddress) }
114119
OCR3Base_SetOCR3Config => { _setOCR3Config(msg, in.senderAddress)}
120+
UpdateSourceChainConfig => {_updateSourceChainConfig(msg, in.senderAddress)}
115121
else => {
116122
// ignore empty messages, "wrong opcode" for others
117123
assert (in.body.isEmpty()) throw 0xFFFF
@@ -122,7 +128,11 @@ fun onInternalMessage(in:InMessage) {
122128
fun _setOCR3Config(msg: OCR3Base_SetOCR3Config, sender: address) {
123129
var st = lazy Storage.load();
124130
st.ownable.requireOwner(sender);
125-
st.ocr3Base.setOcr3Config(msg);
131+
132+
var ocr3Base = st.ocr3Base.load();
133+
ocr3Base.setOcr3Config(msg);
134+
135+
st.ocr3Base = ocr3Base.toCell();
126136
st.store();
127137
}
128138

@@ -135,9 +145,8 @@ fun getMerkleRootID(merkleRoot: uint256): builder {
135145
}
136146

137147
fun commit(msg: Commit, sender: address) {
138-
var st = lazy Storage.load();
148+
var st = Storage.load();
139149

140-
// TODO: verify RMN signatures on blessed roots
141150
val report = msg.report;
142151

143152
// update token/gas prices if any
@@ -154,15 +163,15 @@ fun commit(msg: Commit, sender: address) {
154163
}
155164

156165
// TODO: assert cells are well-formed
157-
var roots = Iterator<MerkleRoot>.new(report.unblessedMerkleRoots);
158-
// TODO: also iterate over blessed roots
166+
var roots = Iterator<MerkleRoot>.new(report.merkleRoots);
159167

160168
while (!roots.empty()) {
161169
val root = roots.next();
162170

163171
// validate lane not cursed
164172

165173
val sourceChainConfig = st.sourceChainConfigs.mustGet(root.sourceChainSelector, ERROR_SOURCE_CHAIN_NOT_ENABLED);
174+
166175
assert(sourceChainConfig.isEnabled,ERROR_SOURCE_CHAIN_NOT_ENABLED);
167176

168177
// validate against sourceChainConfig etc
@@ -196,11 +205,12 @@ fun commit(msg: Commit, sender: address) {
196205
}
197206
},
198207
});
208+
199209
initMsg.send(SEND_MODE_REGULAR);
200210
}
201211

202212
// Verifies signatures and emits Transmitted event
203-
st.ocr3Base.transmit(
213+
st.ocr3Base.load().transmit(
204214
sender,
205215
OCR_PLUGIN_TYPE_COMMIT,
206216
msg.reportContext,
@@ -210,9 +220,8 @@ fun commit(msg: Commit, sender: address) {
210220

211221
emit(CCIP_COMMIT_REPORT_ACCEPTED_TOPIC, CommitReportAccepted {
212222
priceUpdates: report.priceUpdates,
213-
blessedMerkleRoots: report.blessedMerkleRoots,
214-
unblessedMerkleRoots: report.unblessedMerkleRoots,
215-
})
223+
merkleRoots: report.merkleRoots,
224+
});
216225
}
217226

218227
fun _execute(msg: Execute, sender: address) {
@@ -295,7 +304,7 @@ fun _execute(msg: Execute, sender: address) {
295304

296305
// TODO: how do we handle incrementing the nonce? since execution is async this might take a while
297306

298-
st.ocr3Base.transmit(
307+
st.ocr3Base.load().transmit(
299308
sender,
300309
OCR_PLUGIN_TYPE_EXECUTE,
301310
msg.reportContext,
@@ -304,6 +313,14 @@ fun _execute(msg: Execute, sender: address) {
304313
);
305314
}
306315

316+
//todo: should be chainConfigs and take an array
317+
fun _updateSourceChainConfig(msg: UpdateSourceChainConfig, sender: address) {
318+
var st = lazy Storage.load();
319+
st.ownable.requireOwner(sender);
320+
st.sourceChainConfigs.set(msg.sourceChainSelector, msg.config);
321+
st.store();
322+
}
323+
307324
// TODO: handle signals from MerkleRoot (release tokens, execute)
308325
// maybe send these straight to router if router can validate address == deployable(offrampAddress, MerkleRoot, id)
309326
// the payload would need the id & chainSelector so we can calculate/validate offrampAddress & that the merkle root is allowed to send for that ID

contracts/contracts/ccip/onramp.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import "../lib/upgrades/type_and_version.tolk";
55
import "../lib/utils.tolk";
66
import "@stdlib/tvm-dicts";
77

8-
const CCIP_MESSAGE_SENT_TOPIC: int = 0xa45d293c; // crc32("CCIPMessageSent")
8+
const CCIP_MESSAGE_SENT_TOPIC: int = stringCrc32("CCIPMessageSent");
99

1010
struct CCIPMessageSent {
1111
destChainSelector: uint64; // NOTE: both these values are already part of message, is it even important to have?

contracts/contracts/ccip/types.tolk

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ struct Any2TVMRampMessage {
4242
sender: Cell<CrossChainAddress>;
4343
data: cell;
4444
receiver: address;
45-
gasLimit: coins;
46-
tokenAmounts: cell; // vec<Any2TONTokenTransfer>
45+
//gasLimit: coins;
46+
tokenAmounts: cell?; // vec<Any2TVMTokenTransfer>
4747
// maybe mark these amounts as slice remaining then parse them by hand to avoid requiring this to be a map<> at send time?
4848
}
4949

@@ -84,14 +84,14 @@ fun Any2TVMRampMessage.generateMessageId(self, metadataHash: uint256): uint256 {
8484
.storeUint(self.header.messageId, 256)
8585
.storeAddress(self.receiver)
8686
.storeUint(self.header.sequenceNumber, 64)
87-
.storeCoins(self.gasLimit)
87+
//.storeCoins(self.gasLimit)
8888
.storeUint(self.header.nonce, 64)
8989
.endCell()
9090
)
9191
// message
9292
.storeRef(self.sender)
9393
.storeRef(self.data)
94-
.storeRef(self.tokenAmounts)
94+
.storeMaybeRef(self.tokenAmounts)
9595
.endCell()
9696
.hash()
9797
}

contracts/contracts/lib/ocr/multi_ocr3_base.tolk

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import "./exit_codes.tolk";
33
import "./../utils.tolk";
44

55

6-
//sha256("OCR3Base_ConfigSet")
7-
const OCR3BASE_CONFIG_SET_TOPIC: int = 0x252df30dc755a76605aaa7d3a9988e2a50c42f58fbb18d267e5455b1b05c3019;
8-
//sha256("OCR3Base_Transmitted")
9-
const OCR3BASE_TRANSMITTED: int = 0x5e5c7df897e863d72f9277ec7832d0794aebac23abe5cfbd11079f20fd96c851;
6+
//crc32("OCR3Base_ConfigSet")
7+
const OCR3BASE_CONFIG_SET_TOPIC: int = stringCrc32("OCR3Base_ConfigSet");
8+
9+
//crc32("OCR3Base_Transmitted")
10+
const OCR3BASE_TRANSMITTED: int = stringCrc32("OCR3Base_Transmitted");
1011

1112
/// @notice Event, triggers a new run of the offchain reporting protocol.
1213
/// @param ocrPluginType OCR plugin type for which the config was set.

0 commit comments

Comments
 (0)