Skip to content
Open
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
9 changes: 8 additions & 1 deletion contracts/contracts/ccip/offramp/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import "../merkle_root/messages"
import "../../lib/receiver/messages"
import "../merkle_root/storage"

const CONTRACT_VERSION = "0.0.3";
const CONTRACT_VERSION = "0.0.4";

fun onInternalMessage(in:InMessage) {
val msg = lazy OffRamp_InMessage.fromSlice(in.body);
Expand Down Expand Up @@ -382,6 +382,9 @@ fun _updateSourceChainConfig(msg: OffRamp_UpdateSourceChainConfig, sender: addre
isRMNVerificationDisabled: true, // RMN verification is always disabled
onRamp: msg.config.onRamp,
};
emit(SOURCE_CHAIN_SELECTOR_ADDED_TOPIC, SourceChainSelectorAdded {
sourceChainSelector: msg.sourceChainSelector,
})
} else {
// OnRamp updates should only happen due to a misconfiguration.
// If an OnRamp is misconfigured, no reports should have been
Expand All @@ -393,6 +396,10 @@ fun _updateSourceChainConfig(msg: OffRamp_UpdateSourceChainConfig, sender: addre
}
st.sourceChainConfigs.set(msg.sourceChainSelector, config);
st.store();
emit(SOURCE_CHAIN_CONFIG_UPDATED_TOPIC, SourceChainConfigUpdated {
sourceChainSelector: msg.sourceChainSelector,
sourceChainConfig: config,
})
}

@pure @inline
Expand Down
13 changes: 11 additions & 2 deletions contracts/contracts/ccip/offramp/events.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ struct ExecutionStateChanged {
//returnData? probably not
}

const CCIP_COMMIT_REPORT_ACCEPTED_TOPIC: int = stringCrc32("CommitReportAccepted");

const CCIP_COMMIT_REPORT_ACCEPTED_TOPIC: int = stringCrc32("CCIPCommitReportAccepted");
struct CommitReportAccepted {
merkleRoot: MerkleRoot? // vec<MerkleRoots>
priceUpdates: Cell<PriceUpdates>?;
}

const SOURCE_CHAIN_SELECTOR_ADDED_TOPIC: int = stringCrc32("SourceChainSelectorAdded");
struct SourceChainSelectorAdded {
sourceChainSelector: uint64;
}

const SOURCE_CHAIN_CONFIG_UPDATED_TOPIC: int = stringCrc32("SourceChainConfigUpdated");
struct SourceChainConfigUpdated {
sourceChainSelector: uint64;
sourceChainConfig: SourceChainConfig;
}

//TODO not used, remove?
struct SkippedAlreadyExecuted {
Expand Down
17 changes: 13 additions & 4 deletions contracts/contracts/ccip/onramp/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import "../router/messages"
import "../../lib/jetton/messages"
import "../../lib/jetton/messages_extended"

const CONTRACT_VERSION = "0.0.3";
const CONTRACT_VERSION = "0.0.4";

fun onInternalMessage(in: InMessage) {
val msg = lazy OnRamp_InMessage.fromSlice(in.body);
Expand Down Expand Up @@ -241,20 +241,29 @@ fun applyDestChainConfigUpdates(mutate st: OnRamp_Storage, updates: cell) {
while (!iter.empty()) {
val update = iter.next();
// create or update entries
var config: OnRamp_DestChainConfig;
val entry = st.destChainConfigs.get(update.destChainSelector);
if (entry.isFound) {
var config = entry.loadValue();
config = entry.loadValue();
config.router = update.router;
config.allowlistEnabled = update.allowlistEnabled;
st.destChainConfigs.replaceAndGetPrevious(update.destChainSelector, config);
} else {
st.destChainConfigs.set(update.destChainSelector, OnRamp_DestChainConfig {
config = OnRamp_DestChainConfig {
router: update.router,
sequenceNumber: 0,
allowlistEnabled: update.allowlistEnabled,
allowedSenders: createEmptyMap(),
})
};
st.destChainConfigs.set(update.destChainSelector, config);
emit(DEST_CHAIN_SELECTOR_ADDED_TOPIC, DestChainSelectorAdded {
destChainSelector: update.destChainSelector
});
}
emit(DEST_CHAIN_CONFIG_UPDATED_TOPIC, DestChainConfigUpdated {
destChainSelector: update.destChainSelector,
destChainConfig: config,
});
}
}

Expand Down
11 changes: 11 additions & 0 deletions contracts/contracts/ccip/onramp/events.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@ const CCIP_MESSAGE_SENT_TOPIC: int = stringCrc32("CCIPMessageSent");
struct CCIPMessageSent {
message: TVM2AnyRampMessage;
}

const DEST_CHAIN_SELECTOR_ADDED_TOPIC: int = stringCrc32("DestChainSelectorAdded");
struct DestChainSelectorAdded {
destChainSelector: uint64;
}

const DEST_CHAIN_CONFIG_UPDATED_TOPIC: int = stringCrc32("DestChainConfigUpdated");
struct DestChainConfigUpdated {
destChainSelector: uint64;
destChainConfig: OnRamp_DestChainConfig;
}
91 changes: 88 additions & 3 deletions contracts/tests/Logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@ import * as CCIPLogs from '../wrappers/ccip/Logs'
import * as OCR3Logs from '../wrappers/libraries/ocr/Logs'
import * as ReceiverLogs from '../wrappers/examples/ccip/Logs'
import { fromSnakeData } from '../src/utils/types'
import { MerkleRoot, merkleRootFromSlice, priceUpdatesFromCell } from '../wrappers/ccip/OffRamp'
import {
MerkleRoot,
merkleRootFromSlice,
priceUpdatesFromCell,
sourceChainConfigFromSlice,
} from '../wrappers/ccip/OffRamp'
import { prettifyAddressesMap } from './utils/prettyPrint'
import { crc32 } from 'zlib'
import * as OR from '../wrappers/ccip/OnRamp'

// https://github.com/ton-blockchain/liquid-staking-contract/blob/1f4e9badbed52a4cf80cc58e4bb36ed375c6c8e7/utils.ts#L269-L294
export const getExternals = (transactions: BlockchainTransaction[]) => {
Expand All @@ -16,7 +23,7 @@ export const getExternals = (transactions: BlockchainTransaction[]) => {
export const testLog = (
message: Message,
from: Address,
topic: number | bigint,
topic: string,
matcher?: (body: Cell) => boolean,
) => {
if (message.info.type !== 'external-out') {
Expand All @@ -25,7 +32,7 @@ export const testLog = (
}
if (!message.info.src.equals(from)) return false
if (!message.info.dest) return false
if (message.info.dest!.value !== BigInt(topic)) return false
if (message.info.dest!.value !== BigInt(crc32(topic))) return false
if (matcher !== undefined) {
if (!message.body) console.log('No body')
return matcher(message.body)
Expand Down Expand Up @@ -55,6 +62,10 @@ type LogTypeMap = {
[CCIPLogs.LogTypes.CCIPMessageSent]: DeepPartial<CCIPLogs.CCIPMessageSent>
[CCIPLogs.LogTypes.CCIPCommitReportAccepted]: DeepPartial<CCIPLogs.CCIPCommitReportAccepted>
[CCIPLogs.LogTypes.ExecutionStateChanged]: DeepPartial<CCIPLogs.ExecutionStateChanged>
[CCIPLogs.LogTypes.SourceChainSelectorAdded]: CCIPLogs.SourceChainSelectorAdded
[CCIPLogs.LogTypes.SourceChainConfigUpdated]: CCIPLogs.SourceChainConfigUpdated
[CCIPLogs.LogTypes.DestChainSelectorAdded]: CCIPLogs.DestChainSelectorAdded
[CCIPLogs.LogTypes.DestChainConfigUpdated]: DeepPartial<CCIPLogs.DestChainConfigUpdated>
[OCR3Logs.LogTypes.OCR3BaseConfigSet]: OCR3Logs.OCR3BaseConfigSet
[OCR3Logs.LogTypes.OCR3BaseTransmitted]: DeepPartial<OCR3Logs.OCR3BaseTransmitted>
[ReceiverLogs.LogTypes.ReceiverCCIPMessageReceived]: ReceiverLogs.ReceiverCCIPMessageReceived
Expand Down Expand Up @@ -87,6 +98,18 @@ const handlers: { [K in CombinedLogType]: Handler<K> } = {
[CCIPLogs.LogTypes.ExecutionStateChanged]: (x, from, match) =>
testLogCCIPExecutionStateChanged(x, from, match as DeepPartial<CCIPLogs.ExecutionStateChanged>),

[CCIPLogs.LogTypes.SourceChainSelectorAdded]: (x, from, match) =>
testLogSourceChainSelectorAdded(x, from, match as CCIPLogs.SourceChainSelectorAdded),

[CCIPLogs.LogTypes.SourceChainConfigUpdated]: (x, from, match) =>
testLogSourceChainConfigUpdated(x, from, match as CCIPLogs.SourceChainConfigUpdated),

[CCIPLogs.LogTypes.DestChainSelectorAdded]: (x, from, match) =>
testLogDestChainSelectorAdded(x, from, match as CCIPLogs.DestChainSelectorAdded),

[CCIPLogs.LogTypes.DestChainConfigUpdated]: (x, from, match) =>
testLogDestChainConfigUpdated(x, from, match as DeepPartial<CCIPLogs.DestChainConfigUpdated>),

[ReceiverLogs.LogTypes.ReceiverCCIPMessageReceived]: (x, from, match) =>
testLogReceiverCCIPMessageReceived(x, from, match as ReceiverLogs.ReceiverCCIPMessageReceived),

Expand Down Expand Up @@ -295,6 +318,68 @@ export const testLogReceiverCCIPMessageReceived = (
})
}

export const testLogSourceChainSelectorAdded = (
message: Message,
from: Address,
match: CCIPLogs.SourceChainSelectorAdded,
) => {
return testLog(message, from, CCIPLogs.LogTypes.SourceChainSelectorAdded, (x) => {
const cs = x.beginParse()
const msg = {
sourceChainSelector: cs.loadUintBig(64),
}
equalsObject(msg, match)
return true
})
}

export const testLogSourceChainConfigUpdated = (
message: Message,
from: Address,
match: CCIPLogs.SourceChainConfigUpdated,
) => {
return testLog(message, from, CCIPLogs.LogTypes.SourceChainConfigUpdated, (x) => {
const cs = x.beginParse()
const msg = {
sourceChainSelector: cs.loadUintBig(64),
config: sourceChainConfigFromSlice(cs),
}
equalsObject(msg, match)
return true
})
}

export const testLogDestChainSelectorAdded = (
message: Message,
from: Address,
match: CCIPLogs.DestChainSelectorAdded,
) => {
return testLog(message, from, CCIPLogs.LogTypes.DestChainSelectorAdded, (x) => {
const cs = x.beginParse()
const msg = {
destChainSelector: cs.loadUintBig(64),
}
equalsObject(msg, match)
return true
})
}

export const testLogDestChainConfigUpdated = (
message: Message,
from: Address,
match: DeepPartial<CCIPLogs.DestChainConfigUpdated>,
) => {
return testLog(message, from, CCIPLogs.LogTypes.DestChainConfigUpdated, (x) => {
const cs = x.beginParse()
const msg = {
destChainSelector: cs.loadUintBig(64),
config: OR.builder.data.destChainConfig().load(cs),
}
matchesObject(msg, match)
return true
})
}

function matchesObject(obj, match) {
expect(obj).toMatchObject(match)
}
Expand Down
19 changes: 16 additions & 3 deletions contracts/tests/ccip/CCIPRouter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as jetton from '../../wrappers/jetton/JettonWallet'
import { dump } from '../utils/prettyPrint'
import { CellCodec, facilityId } from '../../wrappers/utils'
import { crc32 } from 'zlib'
import { CCIP_SEND_EXECUTOR_FACILITY_ID } from '../../wrappers/ccip/OnRamp'
import { CCIP_SEND_EXECUTOR_FACILITY_ID, DestChainConfig } from '../../wrappers/ccip/OnRamp'

const CHAINSEL_EVM_TEST_90000001 = 909606746561742123n
const CHAINSEL_EVM_TEST_90000002 = 5548718428018410741n
Expand Down Expand Up @@ -215,13 +215,19 @@ describe('Router', () => {

// add config for EVM destination
{
const config = {
router: router.address,
sequenceNumber: 0n,
allowlistEnabled: false,
}

const result = await onRamp.sendUpdateDestChainConfigs(deployer.getSender(), {
value: toNano('1'),
destChainConfigs: [
{
destChainSelector: CHAINSEL_EVM_TEST_90000001,
router: router.address,
allowlistEnabled: false,
router: config.router,
allowlistEnabled: config.allowlistEnabled,
},
],
})
Expand All @@ -231,6 +237,13 @@ describe('Router', () => {
deploy: false,
success: true,
})
assertLog(result.transactions, onRamp.address, LogTypes.DestChainSelectorAdded, {
destChainSelector: CHAINSEL_EVM_TEST_90000001,
})
assertLog(result.transactions, onRamp.address, LogTypes.DestChainConfigUpdated, {
destChainSelector: CHAINSEL_EVM_TEST_90000001,
config,
})
}
}
})
Expand Down
24 changes: 18 additions & 6 deletions contracts/tests/ccip/OffRamp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
OFFRAMP_FACILITY_NAME,
MERKLE_ROOT_FACILITY_NAME,
OFFRAMP_FACILITY_ID,
SourceChainConfig,
} from '../../wrappers/ccip/OffRamp'
import { OffRamp, OffRampError } from '../../wrappers/ccip/OffRamp'
import { FeeQuoter } from '../../wrappers/ccip/FeeQuoter'
Expand Down Expand Up @@ -153,11 +154,11 @@ describe('OffRamp', () => {
...overrides,
})

const createDefaultSourceChainConfig = (overrides = {}) => ({
const createDefaultSourceChainConfig = (overrides = {}): SourceChainConfig => ({
router: ROUTER_ADDRESS_TEST,
isEnabled: true,
minSeqNr: 1n,
isRMNVerificationDisabled: false,
isRMNVerificationDisabled: true,
onRamp: bigIntToBuffer(EVM_ONRAMP_ADDRESS_TEST),
...overrides,
})
Expand Down Expand Up @@ -220,14 +221,25 @@ describe('OffRamp', () => {
return result
}

const setupSourceChainConfig = async (isEnabled = true, overrides = {}) => {
const config = createDefaultSourceChainConfig({ isEnabled, ...overrides })
const setupSourceChainConfig = async (overrides = {}, isInitialSetup = true) => {
const config = createDefaultSourceChainConfig({ ...overrides })
const result = await offRamp.sendUpdateSourceChainConfig(deployer.getSender(), {
value: toNano('0.5'),
sourceChainSelector: CHAINSEL_EVM_TEST_90000001,
config,
})
expectSuccessfulTransaction(result, deployer.address, offRamp.address)

if (isInitialSetup) {
assertLog(result.transactions, offRamp.address, CCIPLogs.LogTypes.SourceChainSelectorAdded, {
sourceChainSelector: CHAINSEL_EVM_TEST_90000001,
})
}

assertLog(result.transactions, offRamp.address, CCIPLogs.LogTypes.SourceChainConfigUpdated, {
sourceChainSelector: CHAINSEL_EVM_TEST_90000001,
config: config,
})
return result
}

Expand Down Expand Up @@ -449,7 +461,7 @@ describe('OffRamp', () => {
const root = createMerkleRoot(1n, 1n, rootBytes)

await setupOCRConfig()
await setupSourceChainConfig(false) // disabled source chain
await setupSourceChainConfig({ isEnabled: false }) // disabled source chain

const report: CommitReport = { merkleRoots: [root] }
const reportContext: ReportContext = { configDigest, padding: 0n, sequenceBytes: 0x01 }
Expand Down Expand Up @@ -728,7 +740,7 @@ describe('OffRamp', () => {
await commitReport([root])

// Disable source chain for execution
await setupSourceChainConfig(false)
await setupSourceChainConfig({ isEnabled: false, minSeqNr: 2n }, false)

const report = createExecuteReport([message])
await executeReportExpectingFailure(report, OffRampError.SourceChainNotEnabled)
Expand Down
Loading
Loading