Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions contracts/contracts/ccip/merkle_root/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ fun onInternalMessage(in: InMessage) {
onMarkState(mutate st, msg);
st.store();
}
MerkleRoot_Freeze => {
val st = lazy MerkleRoot_Storage.load();
assert(in.senderAddress == st.owner, MerkleRoot_Error.NotOwner);
onFreeze(st);
}
else => {
// ignore empty messages, "wrong opcode" for others
assert (in.body.isEmpty()) throw 0xFFFF
Expand Down Expand Up @@ -107,6 +112,22 @@ fun onInitExecute(mutate st: MerkleRoot_Storage, msg: MerkleRoot_Validate) {
executeValidated.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}

fun onFreeze(st: MerkleRoot_Storage) {
var seqNum = st.minMsgNr;
while (seqNum <= st.maxMsgNr) {
val state = st.getMessageState(seqNum);
assert(state != ExecutionState.Untouched, MerkleRoot_Error.CannotFreezeWithUntouchedMessages);
seqNum += 1;
}
val drainMsg = createMessage({
bounce: false,
value: 0,
dest: st.owner,
body: createEmptyCell()
});
drainMsg.send(SEND_MODE_CARRY_ALL_BALANCE);
}

get fun typeAndVersion(): (slice, slice) {
return ("com.chainlink.ton.ccip.MerkleRoot", CONTRACT_VERSION);
}
Expand Down
1 change: 1 addition & 0 deletions contracts/contracts/ccip/merkle_root/errors.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ enum MerkleRoot_Error {
SkippedAlreadyExecutedMessage
InvalidState
SeqNumOutOfBounds
CannotFreezeWithUntouchedMessages
}
6 changes: 4 additions & 2 deletions contracts/contracts/ccip/merkle_root/messages.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import "../offramp/messages"

type MerkleRoot_InMessage =
| MerkleRoot_Validate
| MerkleRoot_MarkState;
| MerkleRoot_MarkState
| MerkleRoot_Freeze;

struct (0x038ede91) MerkleRoot_Validate {
message: Cell<Any2TVMRampMessage>,
Expand All @@ -12,12 +13,13 @@ struct (0x038ede91) MerkleRoot_Validate {
gasOverride: coins?,
}

//crc32('MerkleRoot_MarkState')
struct (0x019f4cd2) MerkleRoot_MarkState {
seqNum: uint64,
state: ExecutionState
}

struct (0x0214e358) MerkleRoot_Freeze {}

struct MerkleRoot_Costs{}

fun MerkleRoot_Costs.validate(): int {
Expand Down
33 changes: 33 additions & 0 deletions contracts/contracts/ccip/offramp/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,18 @@ fun onInternalMessage(in:InMessage) {
onSetDynamicConfig(msg);
}
// Sender must be owner
OffRamp_FreezeMerkleRoot => {
val st = lazy Storage.load();
st.ownable.requireOwner(in.senderAddress);
onFreezeMerkleRoot(msg);
}
// Sender must be owner
OffRamp_FreezeReceiveExecutor => {
val st = lazy Storage.load();
st.ownable.requireOwner(in.senderAddress);
onFreezeReceiveExecutor(msg);
}
// Sender must be owner
Withdrawable_Withdraw => {
var st = lazy Storage.load();
st.ownable.requireOwner(in.senderAddress);
Expand Down Expand Up @@ -697,6 +709,27 @@ fun onExecuteValidated(st: Storage, msg: OffRamp_ExecuteValidated, sender: addre
initExecMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
}

//Sends Freeze message to merkle root
fun onFreezeMerkleRoot(msg: OffRamp_FreezeMerkleRoot) {
val freezeMessage = createMessage ({
bounce: true,
value: 0,
dest: msg.merkleRootAddress,
body: MerkleRoot_Freeze{},
});
freezeMessage.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}

fun onFreezeReceiveExecutor(msg: OffRamp_FreezeReceiveExecutor) {
val freezeMessage = createMessage ({
bounce: true,
value: 0,
dest: msg.receiveExecutorAddress,
body: ReceiveExecutor_Freeze{},
});
freezeMessage.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}

/*
Retrieves the Router address associated with a given sourceChainSelector.
Throws an error if the source chain is not enabled in the stored configs.
Expand Down
16 changes: 14 additions & 2 deletions contracts/contracts/ccip/offramp/messages.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@ type OffRamp_InMessage =
| OffRamp_UpdateSourceChainConfigs
| OffRamp_CCIPReceiveConfirm
| OffRamp_CCIPReceiveBounced
| OffRamp_NotifyFailure
| OffRamp_NotifySuccess
| OffRamp_NotifyFailure
| OffRamp_UpdateCursedSubjects
| OffRamp_SetDynamicConfig
| OCR3Base_SetOCR3Config
| OffRamp_UpdateDeployables
| OffRamp_FreezeMerkleRoot
| OffRamp_FreezeReceiveExecutor
| Upgradeable_Upgrade
| Withdrawable_Withdraw;
| Withdrawable_Withdraw
;

struct (0x9d431905) OffRamp_Commit {
queryId: uint64;
Expand Down Expand Up @@ -113,6 +115,16 @@ struct (0xa015e0e2) OffRamp_UpdateDeployables {
merkleRootCode: cell?;
}

struct (0x304e248f) OffRamp_FreezeMerkleRoot {
queryId: uint64;
merkleRootAddress: address;
}

struct (0x97f24208) OffRamp_FreezeReceiveExecutor{
queryId: uint64;
receiveExecutorAddress: address;
}

struct OffRamp_Costs{}

fun OffRamp_Costs.executeValidated(): int {
Expand Down
16 changes: 16 additions & 0 deletions contracts/contracts/ccip/receive_executor/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ fun onInternalMessage(in: InMessage) {
onCCIPReceiveBounced(mutate st, msg);
st.store();
}
ReceiveExecutor_Freeze => {
var st = ReceiveExecutor_Storage.load();
assert(in.senderAddress == st.owner, Error.Unauthorized);
onFreeze(st);
}
else => {
// ignore empty messages, "wrong opcode" for others
assert (in.body.isEmpty()) throw 0xFFFF
Expand Down Expand Up @@ -107,6 +112,17 @@ fun onCCIPReceiveBounced(mutate st: ReceiveExecutor_Storage, msg: ReceiveExecuto
notifyFailure.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}

fun onFreeze(st: ReceiveExecutor_Storage) {
assert(st.state != ReceiveExecutor_MessageState.Untouched, Error.CannotFreezeWithUntouchedState);
val drainMsg = createMessage({
bounce: false,
value: 0,
dest: st.owner,
body: createEmptyCell()
});
drainMsg.send(SEND_MODE_CARRY_ALL_BALANCE);
}

get fun typeAndVersion(): (slice, slice) {
return ("com.chainlink.ton.ccip.ReceiveExecutor", CONTRACT_VERSION);
}
Expand Down
1 change: 1 addition & 0 deletions contracts/contracts/ccip/receive_executor/errors.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ enum Error {
UpdatingStateOfNonExecutedMessage
NotificationFromInvalidReceiver
Unauthorized
CannotFreezeWithUntouchedState
}
5 changes: 4 additions & 1 deletion contracts/contracts/ccip/receive_executor/messages.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import "../offramp/messages"
type ReceiveExecutor_InMessage =
| ReceiveExecutor_InitExecute
| ReceiveExecutor_Bounced
| ReceiveExecutor_Confirm;
| ReceiveExecutor_Confirm
| ReceiveExecutor_Freeze;

struct (0x64cd2fd2) ReceiveExecutor_InitExecute {
gasOverride: coins? = null;
Expand All @@ -17,6 +18,8 @@ struct (0x05dee1bb) ReceiveExecutor_Bounced {
receiver: address
}

struct (0x1571d8c6) ReceiveExecutor_Freeze {}

const RECEIVE_EXECUTOR_COSTS_CONFIRMED_OR_BOUNCED_FEE = ton("0.007");
const RECEIVE_EXECUTOR_COSTS_INIT_EXEC_FEE = ton("0.004");

Expand Down
Loading
Loading