Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
18 changes: 15 additions & 3 deletions contracts/contracts/ccip/ccipsend_executor/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,19 @@ import "../router/messages"
import "../fee_quoter/types"
import "@stdlib/gas-payments"

const CONTRACT_VERSION = "1.6.0";
tolk 1.4.1

const CONTRACT_VERSION = "1.6.1".literalSlice();

contract CCIPSendExecutor {
author: "SmartContract Chainlink Limited SEZC"
version: "1.6.1"
description: "link.chain.ton.ccip.CCIPSendExecutor"

storage: CCIPSendExecutor_Data
storageAtDeployment: CCIPSendExecutor_InitialData
incomingMessages: CCIPSendExecutor_InMessage
}

fun onInternalMessage(in: InMessage) {
val msg = lazy CCIPSendExecutor_InMessage.fromSlice(in.body);
Expand Down Expand Up @@ -153,13 +165,13 @@ fun CCIPSendExecutor<T>.exitWithError(self, error: uint256) {
}

get fun typeAndVersion(): (slice, slice) {
return (CCIPSendExecutor_FACILITY_NAME, CONTRACT_VERSION);
return (CCIPSendExecutor_FACILITY_NAME.literalSlice(), CONTRACT_VERSION);
}

get fun facilityId(): uint16 {
return CCIPSendExecutor_FACILITY_ID;
}

get fun errorCode(local: uint16): uint16 {
return getErrorCode(stringCrc32("link.chain.ton.ccip.CCIPSendExecutor"), local);
return getErrorCode("link.chain.ton.ccip.CCIPSendExecutor".crc32(), local);
}
3 changes: 2 additions & 1 deletion contracts/contracts/ccip/ccipsend_executor/types.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import "../onramp/messages.tolk";

const CCIPSendExecutor_FACILITY_NAME = "link.chain.ton.ccip.CCIPSendExecutor";
const CCIPSendExecutor_FACILITY_ID = 178; // (crc32(<facility>) % 640) + 10
const CCIPSendExecutor_FACILITY_ID = CCIPSendExecutor_FACILITY_NAME.crc32() % 640 + 10; // 178
// NOTE: inlined getFacilityId because compiler doesn't allow custom compile time functions

type CCIPSendExecutor_ID = uint224

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import "types"

tolk 1.2
tolk 1.4.1

const EVM_PRECOMPILE_SPACE = 1024;
const APTOS_PRECOMPILE_SPACE = 0x0b;
Expand Down
2 changes: 1 addition & 1 deletion contracts/contracts/ccip/common/types.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct RampMessageHeader { // 512
nonce: uint64;
}

const LEAF_DOMAIN_SEPARATOR: slice = stringHexToSlice("0000000000000000000000000000000000000000000000000000000000000000");
const LEAF_DOMAIN_SEPARATOR: slice = "0000000000000000000000000000000000000000000000000000000000000000".hexToSlice();

// nolint:opcode : hex encoded bytes4(keccak256("CCIP EVMExtraArgsV2"))
struct (0x181dcf10) GenericExtraArgsV2 {
Expand Down
63 changes: 36 additions & 27 deletions contracts/contracts/ccip/fee_quoter/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,24 @@ import "../../lib/math";
import "../router/messages"
import "../ccipsend_executor/messages"

const CONTRACT_VERSION = "1.6.2";
tolk 1.4.1

contract FeeQuoter {
author: "SmartContract Chainlink Limited SEZC"
version: "1.6.3"
description: "link.chain.ton.ccip.FeeQuoter"

storage: Storage
incomingMessages: FeeQuoter_InMessage
}

const CONTRACT_VERSION = "1.6.3".literalSlice();
const RESERVE = ton("1");

fun requireSupportedVersion(version: slice) {
assert (version.bitsEqual("1.6.2".literalSlice())) throw Upgradeable_Error.VersionMismatch;
}

fun onInternalMessage(in: InMessage) {
val msg = lazy FeeQuoter_InMessage.fromSlice(in.body);
match (msg) {
Expand Down Expand Up @@ -159,7 +174,7 @@ fun updateDestChainConfigs(mutate st: Storage, updates: SnakedCell<FeeQuoter_Upd
dataAvailabilityGasPrice: 0,
timestamp: 0,
}.toCell(),
tokenTransferFeeConfigs: createEmptyMap()
tokenTransferFeeConfigs: []
})
}
}
Expand Down Expand Up @@ -360,8 +375,7 @@ fun validateMessageAndResolveGasLimitForDestination(extraArgs: cell, config: Fee
if (config.chainFamilySelector == CHAIN_FAMILY_SELECTOR_EVM ||
config.chainFamilySelector == CHAIN_FAMILY_SELECTOR_APTOS ||
config.chainFamilySelector == CHAIN_FAMILY_SELECTOR_TVM) {
val gasLimitOpt = resolveGenericGasLimit(extraArgs, config.defaultTxGasLimit, config.maxPerMsgGasLimit);
val gasLimit = gasLimitOpt != null ? gasLimitOpt : 0;
val gasLimit = resolveGenericGasLimit(extraArgs, config.defaultTxGasLimit, config.maxPerMsgGasLimit);
validateDestFamilyAddress(config.chainFamilySelector, message.receiver, gasLimit);
return gasLimit;
}
Expand Down Expand Up @@ -427,8 +441,12 @@ fun validateMessageAndResolveGasLimitForDestination(extraArgs: cell, config: Fee
}
}

fun resolveGenericGasLimit(extraArgs: cell, defaultTxGasLimit: uint32, maxPerMsgGasLimit: uint32): int?{
return parseGenericExtraArgs(extraArgs, defaultTxGasLimit, maxPerMsgGasLimit).gasLimit;
fun resolveGenericGasLimit(extraArgs: cell, defaultTxGasLimit: uint32, maxPerMsgGasLimit: uint32): int {
val gasLimit = parseGenericExtraArgs(extraArgs, defaultTxGasLimit, maxPerMsgGasLimit).gasLimit;
if (gasLimit != null) {
return gasLimit as int
}
return 0;
}

fun parseGenericExtraArgs(extraArgs: cell, defaultTxGasLimit: uint32, maxPerMsgGasLimit: uint32): GenericExtraArgsV2 {
Expand Down Expand Up @@ -543,23 +561,22 @@ get fun tokenPrice(token: address): TimestampedPrice {
return entry.loadValue();
}

// vec<TimestampedPrice>
get fun tokenPrices(tokens: tuple): tuple {
get fun tokenPrices(tokens: array<address>): array<Cell<TimestampedPrice>?> {
val st = lazy Storage.load();
var list: tuple = createEmptyTuple();
var iter = TupleIterator<address>.new(tokens);
var prices: array<Cell<TimestampedPrice>?> = [];
var tokenIterator = ArrayIterator<address>.new(tokens);

while(!iter.empty()) {
val token = iter.next();
while(!tokenIterator.empty()) {
val token = tokenIterator.next();
val entry = st.usdPerToken.get(token);
// NOTE: Need to skip missing items as nil entries rather than fail the query
if (entry.isFound) {
list.push(entry.loadValue().toCell());
prices.push(entry.loadValue().toCell());
} else {
list.push(null);
prices.push(null);
}
}
return list;
return prices;
}

get fun destinationChainGasPrice(destChainSelector: uint64): cell {
Expand All @@ -580,7 +597,7 @@ get fun premiumMultiplierWeiPerEth(token: address): uint256 {
}

// vec<address>
get fun feeTokens(): tuple? {
get fun feeTokens(): lisp_list<address> {
val st = lazy Storage.load();
var feeTokens = st.premiumMultiplierWeiPerEth;
return keysLispList(feeTokens);
Expand Down Expand Up @@ -637,18 +654,18 @@ get fun pendingOwner(): address? {
}

get fun typeAndVersion(): (slice, slice) {
return (FeeQuoter_FACILITY_NAME, CONTRACT_VERSION);
return (FeeQuoter_FACILITY_NAME.literalSlice(), CONTRACT_VERSION);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these constants x__FACILITY_NAME and CONTRACT_VERSION - is there a specific reason we additionally need those everywhere vs. just defining the type and version once in the typeAndVersion() func?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite typeAndVersion being a pure and constant function that could be computed at compile time, comp-time methods like crc32 only work with constant strings.

}

get fun facilityId(): uint16 {
return FeeQuoter_FACILITY_ID;
}

get fun errorCode(local: uint16): uint16 {
return getErrorCode(stringCrc32("link.chain.ton.ccip.FeeQuoter"), local);
return getErrorCode("link.chain.ton.ccip.FeeQuoter".crc32(), local);
}

get fun destChainSelectors(): tuple? {
get fun destChainSelectors(): lisp_list<uint64> {
val st = lazy Storage.load();
var d = st.destChainConfigs;
return keysLispList(d)!;
Expand All @@ -667,13 +684,5 @@ fun migrate(storage: cell, version: slice): cell {
return st.toCell();
}

fun requireSupportedVersion(version: slice) {
assert (
version.bitsEqual("1.6.0")
|| version.bitsEqual("1.6.1")
)
throw Upgradeable_Error.VersionMismatch;
}

@method_id(1001)
fun version(): slice { return CONTRACT_VERSION; }
4 changes: 2 additions & 2 deletions contracts/contracts/ccip/fee_quoter/events.tolk
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: BUSL-1.1

const USD_PER_TOKEN_UPDATED_TOPIC: int = stringCrc32("UsdPerTokenUpdated");
const USD_PER_TOKEN_UPDATED_TOPIC: int = "UsdPerTokenUpdated".crc32();
struct UsdPerTokenUpdated {
sourceToken: address
usdPerToken: uint224
timestamp: uint64
}

const USD_PER_UNIT_GAS_UPDATED: int = stringCrc32("UsdPerUnitGasUpdated");
const USD_PER_UNIT_GAS_UPDATED: int = "UsdPerUnitGasUpdated".crc32();
struct UsdPerUnitGasUpdated {
destChainSelector: uint64
executionGasPrice: uint112
Expand Down
3 changes: 2 additions & 1 deletion contracts/contracts/ccip/fee_quoter/types.tolk
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import "../../lib/utils"

const FeeQuoter_FACILITY_NAME = "link.chain.ton.ccip.FeeQuoter";
const FeeQuoter_FACILITY_ID = 344; // (crc32(<facility>) % 640) + 10
const FeeQuoter_FACILITY_ID = FeeQuoter_FACILITY_NAME.crc32() % 640 + 10; // 344
// NOTE: inlined getFacilityId because compiler doesn't allow custom compile time functions

struct TimestampedPrice {
value: uint224;
Expand Down
17 changes: 14 additions & 3 deletions contracts/contracts/ccip/merkle_root/contract.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@ import "errors"
import "storage"
import "types"

tolk 1.4.1

// MerkleRoot contract
// Root is commited on Commit Reports and the existence of this contract is used to validate Execute Reports

const CONTRACT_VERSION = "1.6.0";
const CONTRACT_VERSION = "1.6.1".literalSlice();

contract MerkleRoot {
author: "SmartContract Chainlink Limited SEZC"
version: "1.6.1"
description: "link.chain.ton.ccip.MerkleRoot"

storage: MerkleRoot_Storage
incomingMessages: MerkleRoot_InMessage
}

fun onInternalMessage(in: InMessage) {
val msg = lazy MerkleRoot_InMessage.fromSlice(in.body);
Expand Down Expand Up @@ -113,13 +124,13 @@ fun onInitExecute(mutate st: MerkleRoot_Storage, msg: MerkleRoot_Validate) {
}

get fun typeAndVersion(): (slice, slice) {
return (MerkleRoot_FACILITY_NAME, CONTRACT_VERSION);
return (MerkleRoot_FACILITY_NAME.literalSlice(), CONTRACT_VERSION);
}

get fun facilityId(): uint16 {
return MerkleRoot_FACILITY_ID;
}

get fun errorCode(local: uint16): uint16 {
return getErrorCode(stringCrc32("link.chain.ton.ccip.MerkleRoot"), local);
return getErrorCode("link.chain.ton.ccip.MerkleRoot".crc32(), local);
}
3 changes: 2 additions & 1 deletion contracts/contracts/ccip/merkle_root/types.tolk
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: BUSL-1.1
const MerkleRoot_FACILITY_NAME = "link.chain.ton.ccip.MerkleRoot";
const MerkleRoot_FACILITY_ID = 186; // (crc32(<facility>) % 640) + 10
const MerkleRoot_FACILITY_ID = MerkleRoot_FACILITY_NAME.crc32() % 640 + 10; // 186
// NOTE: inlined getFacilityId because compiler doesn't allow custom compile time functions
37 changes: 23 additions & 14 deletions contracts/contracts/ccip/offramp/contract.tolk
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// SPDX-License-Identifier: BUSL-1.1
import "../../lib/versioning/upgradeable"
import "../../lib/deployable/types"
import "../../lib/deployable/namespace"
import "../../lib/access/ownable_2step.tolk"
import "../../lib/funding/withdrawable.tolk"
import "../../lib/crypto/merkle_multi_proof.tolk"
import "../../lib/ocr/multi_ocr3_base"
import "../../lib/ocr/types"
import "../../lib/utils.tolk"
import "../../lib/receiver/types"
import "../../lib/deployable/namespace"
import "../rmn_remote/lib.tolk"

import "../common/types.tolk"

Expand All @@ -25,7 +26,19 @@ import "types"
import "storage"
import "events"

const CONTRACT_VERSION = "1.6.2";
tolk 1.4.1

contract OffRamp {
author: "SmartContract Chainlink Limited SEZC"
version: "1.6.3"
description: "link.chain.ton.ccip.OffRamp"

storage: Storage
incomingMessages: OffRamp_InMessage
}


const CONTRACT_VERSION = "1.6.3".literalSlice();
const RESERVE = ton("5");
const MIN_GASLIMIT = ton("0.025");

Expand Down Expand Up @@ -242,11 +255,7 @@ fun migrate(storage: cell, version: slice): cell {
}

fun requireSupportedVersion(version: slice) {
assert (
version.bitsEqual("1.6.0")
|| version.bitsEqual("1.6.1")
)
throw Upgradeable_Error.VersionMismatch;
assert (version.bitsEqual("1.6.2".literalSlice())) throw Upgradeable_Error.VersionMismatch;
}

@method_id(1001)
Expand Down Expand Up @@ -691,10 +700,10 @@ fun onExecuteSingleReport(report: ExecutionReport, gasOverride: coins?, value: c
// This acts as an extra check to ensure the message source chain selector matches the report's source chain.
assert(message.header.sourceChainSelector == report.sourceChainSelector, Error.SourceChainSelectorMismatch);

var leafTuple: tuple = createEmptyTuple();
leafTuple.push(message.generateMessageId(metadataHash));
var leaves: array<uint256> = [];
leaves.push(message.generateMessageId(metadataHash));

val root = merkleRoot(TupleIterator<uint256>.new(leafTuple), report.proofs.iter(), report.proofFlagBits);
val root = merkleRoot(ArrayIterator<uint256>.new(leaves), report.proofs.iter(), report.proofFlagBits);

// send message to MerkleRoot (execute)
val executeMsg = createMessage({
Expand Down Expand Up @@ -936,7 +945,7 @@ get fun latestPriceSequenceNumber(): uint64 {
return st.latestPriceSequenceNumber
}

get fun sourceChainSelectors(): tuple? {
get fun sourceChainSelectors(): lisp_list<uint64> {
val st = lazy Storage.load();
var d = st.sourceChainConfigs;
return keysLispList(d)!;
Expand Down Expand Up @@ -971,7 +980,7 @@ get fun verifyNotCursed(subject: uint128): bool {
return !st.cursedSubjects.isCursed(subject);
}

get fun cursedSubjects(): tuple? {
get fun cursedSubjects(): lisp_list<uint128> {
val st = lazy Storage.load();
return keysLispList(st.cursedSubjects.data)!;
}
Expand Down Expand Up @@ -1005,15 +1014,15 @@ get fun pendingOwner(): address? {
}

get fun typeAndVersion(): (slice, slice) {
return (OffRamp_FACILITY_NAME, CONTRACT_VERSION);
return (OffRamp_FACILITY_NAME.literalSlice(), CONTRACT_VERSION);
}

get fun facilityId(): uint16 {
return OffRamp_FACILITY_ID;
}

get fun errorCode(local: uint16): uint16 {
return getErrorCode(stringCrc32("link.chain.ton.ccip.OffRamp"), local);
return getErrorCode("link.chain.ton.ccip.OffRamp".crc32(), local);
}

get fun reserve(): coins {
Expand Down
Loading
Loading