diff --git a/contracts/Acton.toml b/contracts/Acton.toml index c7e03e988..676993f95 100644 --- a/contracts/Acton.toml +++ b/contracts/Acton.toml @@ -62,6 +62,12 @@ src = "contracts/mcms/mcms.tolk" domain = "mcms" depends = [] +[contracts.Test_RemainingBitsOrRef] +display-name = "link.chain.ton.test.lib.RemainingBitsOrRef" +src = "contracts/test/lib/remaining_bits_or_ref.tolk" +domain = "test" +depends = [] + # fmt is not very mature yet [fmt] width = 100 diff --git a/contracts/contracts/ccip/onramp/messages.tolk b/contracts/contracts/ccip/onramp/messages.tolk index cb386370c..4e1d1ad37 100644 --- a/contracts/contracts/ccip/onramp/messages.tolk +++ b/contracts/contracts/ccip/onramp/messages.tolk @@ -2,6 +2,7 @@ import "types" import "../router/messages" import "../../lib/utils" +import "../../lib/remaining_bits_or_ref" import "../../lib/versioning/upgradeable" import "../ccipsend_executor/messages" import "../fee_quoter/messages" diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index 2b8dc9164..2f6b5a03f 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -2,6 +2,7 @@ import "types" import "../common/types.tolk" import "../../lib/utils" +import "../../lib/remaining_bits_or_ref" import "../../lib/funding/withdrawable.tolk"; import "../../lib/versioning/upgradeable" import "../../lib/receiver/types" diff --git a/contracts/contracts/lib/remaining_bits_or_ref.tolk b/contracts/contracts/lib/remaining_bits_or_ref.tolk new file mode 100644 index 000000000..15805cff6 --- /dev/null +++ b/contracts/contracts/lib/remaining_bits_or_ref.tolk @@ -0,0 +1,33 @@ +// This type works as a wrapper for RemainingBitsAndRefs that implements +// automatic serialization/deserialization. It determines whether to store the +// data directly as bits or as a reference to a cell, depending on available +// space. +type RemainingBitsOrRef = T; + +fun RemainingBitsOrRef.packToBuilder(self, mutate b: builder): void { + val contentCell = (self as T).toCell(); + val (contentBits, contentRefs) = contentCell.beginParse().remainingBitsAndRefsCount(); + val availableBits = 1023 - b.bitsCount(); + val availableRefs = 4 - b.refsCount(); + if (availableBits < contentBits + 1 || availableRefs < contentRefs) { + // not enough space, create a new cell + b.storeBool(true); + b.storeRef(contentCell); + } else { + // can be inlined + b.storeBool(false); + b.storeSlice(contentCell.beginParse()); + } +} + +fun RemainingBitsOrRef.unpackFromSlice(mutate s: slice): RemainingBitsOrRef { + val isRef = s.loadBool(); + var result: RemainingBitsOrRef; + if (isRef) { + val c = s.loadRef(); + result = T.fromCell(c) as RemainingBitsOrRef; + } else { + result = T.fromSlice(s) as RemainingBitsOrRef; + } + return result; +} \ No newline at end of file diff --git a/contracts/contracts/lib/utils.tolk b/contracts/contracts/lib/utils.tolk index 23fb29965..adeef2cc1 100644 --- a/contracts/contracts/lib/utils.tolk +++ b/contracts/contracts/lib/utils.tolk @@ -239,34 +239,3 @@ fun keysLispList(dict: map): lisp_list { } ; return lisplist; } - -// This type works as a wrapper for RemainingBitsAndRefs that implements -// automatic serialization/deserialization. It determines whether to store the -// data directly as bits or as a reference to a cell, depending on available -// space. -type RemainingBitsOrRef = T; - -// TODO investigate why this was being ignored in 1.2 - -// fun RemainingBitsOrRef.packToBuilder(self, mutate b: builder): void { -// val serialized = (self as T).toCell(); -// val (nBits, _) = serialized.beginParse().remainingBitsAndRefsCount(); -// if (b.remainingSpace() < nBits + 1) { -// // not enough space, create a new cell -// b.storeBool(true); -// b.storeRef(serialized); -// } else { -// b.storeBool(false); -// b.storeSlice(serialized.beginParse()); -// } -// } - -// fun RemainingBitsOrRef.unpackFromSlice(mutate s: slice): RemainingBitsOrRef { -// val isRef = s.loadBool(); -// if (isRef) { -// val c = s.loadRef(); -// return T.fromCell(c) as RemainingBitsOrRef; -// } else { -// return T.fromSlice(s) as RemainingBitsOrRef; -// } -// } diff --git a/contracts/contracts/test/lib/remaining_bits_or_ref.tolk b/contracts/contracts/test/lib/remaining_bits_or_ref.tolk new file mode 100644 index 000000000..b61d85f06 --- /dev/null +++ b/contracts/contracts/test/lib/remaining_bits_or_ref.tolk @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +tolk 1.4.1 + +import "../../lib/remaining_bits_or_ref" + + +contract RemainingBitsOrRefTestWrapper { + author: "SmartContract Chainlink Limited SEZC" + version: "1.6.1" + description: "Test wrapper for RemainingBitsOrRef library" +} + +fun onInternalMessage(in: InMessage) { + assert (in.body.isEmpty()) throw 0xFFFF +} + +const MAX_CELLS = 4; + +struct IncompleteCell { + _1: uint256 = 1 +} + +// 1 bit is used to indicate whether the data is stored inline or as a reference +struct FullCell { + _1: uint256 = 1 + _2: uint256 = 2 + _3: uint256 = 3 + _4: RemainingBitsOrRef = 4 +} + +struct JustOverFullCell { + _1: uint256 = 1 + _2: uint256 = 2 + _3: uint256 = 3 + _4: RemainingBitsOrRef = 4 +} + +struct _WithReference { + _12: uint254 = 12 + _cell: Cell +} + +fun New_WithReference(): _WithReference { + return _WithReference { _cell: (34 as uint256).toCell() }; +} + +struct InlinedWithReference { + _1: uint256 = 1 + _2: uint256 = 2 + _3: uint256 = 3 + _4: RemainingBitsOrRef<_WithReference> +} + +fun NewInlinedWithReference(): InlinedWithReference { + return InlinedWithReference { _4: New_WithReference() }; +} + +struct _TooManyReferences { + _1: Cell + _2: Cell + _3: Cell + _4: Cell +} + +fun _newTooManyReferences(): _TooManyReferences { + return _TooManyReferences { + _1: (11 as uint256).toCell(), + _2: (12 as uint256).toCell(), + _3: (13 as uint256).toCell(), + _4: (14 as uint256).toCell(), + } +} + +struct TooManyReferencesToInline { + _1: Cell + _2: Cell + _3: Cell + _4: RemainingBitsOrRef<_TooManyReferences> +} + +fun NewTooManyReferencesToInline(): TooManyReferencesToInline { + return TooManyReferencesToInline { + _1: (1 as uint256).toCell(), + _2: (2 as uint256).toCell(), + _3: (3 as uint256).toCell(), + _4: _newTooManyReferences() + } +} + +/// expected to fit in 256 bits of a single cell +get fun test_incomplete_cell(): cell { + return RemainingBitsOrRef { }.toCell(); +} + +/// expected to fit in 1023 bits of a single cell +get fun test_full_cell(): cell { + return RemainingBitsOrRef { }.toCell(); +} + +/// expected to require 1024 bits (1 more than full cell), so the 4th field should be stored as a reference +get fun test_just_over_full_cell(): cell { + return JustOverFullCell { }.toCell(); +} + +/// expected to fit in 256 bits of a single cell, and the reference come from the root cell +get fun test_inlined_with_reference(): cell { + return NewInlinedWithReference().toCell(); +} + +/// expected to be stored as a reference, because inlining would require 5 references which is more than the maximum of 4 allowed +get fun test_too_many_references_to_inline(): cell { + return NewTooManyReferencesToInline().toCell(); +} \ No newline at end of file diff --git a/contracts/tests/ccip/onramp/OnRamp.getFee.spec.ts b/contracts/tests/ccip/onramp/OnRamp.getFee.spec.ts index 3b78b7fd3..7b00eece7 100644 --- a/contracts/tests/ccip/onramp/OnRamp.getFee.spec.ts +++ b/contracts/tests/ccip/onramp/OnRamp.getFee.spec.ts @@ -69,10 +69,11 @@ describe('OnRamp - Get Fee', () => { }) it('should forward get fee to fee quoter', async () => { + const requestCtx = beginCell().storeUint(42, 32).asSlice() // arbitrary context const result = await onramp.sendGetValidatedFee(mockRouter.getSender(), { value: toNano('0.5'), msg: ccipSend, - context: beginCell().storeUint(42, 32).endCell(), // arbitrary context + context: requestCtx, }) expect(result.transactions).toHaveTransaction({ @@ -105,9 +106,24 @@ describe('OnRamp - Get Fee', () => { if (outMsg.info.type !== 'internal') { throw new Error('Unexpected message type') } - expect(outMsg.body.beginParse().loadUint(32)).toBe(fq.opcodes.in.getValidatedFee) - const decoded = fq.builder.message.in.getValidatedFee.load(outMsg.body.beginParse()) - expect(decoded.msg).toEqual(ccipSend) + const outMsgBody = outMsg.body.beginParse() + expect(outMsgBody.preloadUint(32)).toBe(fq.opcodes.in.getValidatedFee) + + // The OnRamp wraps the user context with the router address (OnRamp_GetValidatedFeeContext) + const expectedContext = or.builder.data.getValidatedFeeContext + .encode({ + onrampContext: mockRouter.address, + userContext: beginCell().storeUint(42, 32).asSlice(), + }) + .asSlice() + const expectedOutMsgBody = fq.builder.message.in.getValidatedFee + .encode({ + msg: ccipSend, + context: expectedContext, + }) + .asCell() + + expect(outMsg.body.toString()).toEqual(expectedOutMsgBody.toString()) }) it('should throw error if message validated comes from non-feequoter', async () => { diff --git a/contracts/tests/ccip/router/Router.getFee.spec.ts b/contracts/tests/ccip/router/Router.getFee.spec.ts index f1e1c4d5f..e383453f0 100644 --- a/contracts/tests/ccip/router/Router.getFee.spec.ts +++ b/contracts/tests/ccip/router/Router.getFee.spec.ts @@ -4,6 +4,7 @@ import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox' import { asSnakeDataUint, fromSnakeData, WRAPPED_NATIVE } from '../../../src/utils' import * as coverage from '../../coverage/coverage' +import * as remainingBitsOrRef from '../../../wrappers/libraries/utils/RemainingBitsOrRef' import * as rtOld from '../../../wrappers/ccip/Router' import * as rt from '../../../wrappers/gen/ccip/Router' import * as or from '../../../wrappers/ccip/OnRamp' @@ -55,6 +56,12 @@ describe('Router', () => { CrossChainAddress__packToBuilder, CrossChainAddress__unpackFromSlice, ) + + rt.Router.registerCustomPackUnpack( + 'RemainingBitsOrRef', + remainingBitsOrRef.builder.encode, + remainingBitsOrRef.builder.load, + ) }) beforeEach(async () => { diff --git a/contracts/tests/lib/remaining_bits_or_ref/RemainingBitsOrRef.spec.ts b/contracts/tests/lib/remaining_bits_or_ref/RemainingBitsOrRef.spec.ts new file mode 100644 index 000000000..d880876fc --- /dev/null +++ b/contracts/tests/lib/remaining_bits_or_ref/RemainingBitsOrRef.spec.ts @@ -0,0 +1,216 @@ +import * as s from '@ton/sandbox' +import * as c from '@ton/core' + +import * as tw from '../../../wrappers/gen/test/Test_RemainingBitsOrRef' +import { contractCode } from '../../../wrappers/codeLoader' +import { builder as remainingBitsOrRefCodec } from '../../../wrappers/libraries/utils/RemainingBitsOrRef' + +type RemainingEncoder = (data: c.Slice, b: c.Builder) => void +type RemainingDecoder = (s: c.Slice) => c.Slice + +// Asserts the payload is stored inline (no ref) +const inlined = { + encode: ((data, b) => { + b.storeBit(false) + b.storeSlice(data) + }) as RemainingEncoder, + load: ((s) => { + expect(s.loadMaybeRef()).toBeNull() + return s + }) as RemainingDecoder, +} + +// Asserts the payload is stored as a reference +const ref = { + encode: ((data, b) => { + b.storeMaybeRef(data.asCell()) + }) as RemainingEncoder, + load: ((s) => { + const r = s.loadMaybeRef() + expect(r).not.toBeNull() + s.endParse() + return r!.beginParse() + }) as RemainingDecoder, +} + +// --- TS struct codecs mirroring the Tolk test structs --- + +const FullCell = { + build: (encode: RemainingEncoder): c.Cell => { + const b = c.beginCell() + b.storeUint(1, 256) + b.storeUint(2, 256) + b.storeUint(3, 256) + const payload = c.beginCell().storeUint(4, 254).endCell().beginParse() + encode(payload, b) + return b.endCell() + }, + load: (cell: c.Cell, decode: RemainingDecoder) => { + const s = cell.beginParse() + expect(s.loadUint(256)).toBe(1) + expect(s.loadUint(256)).toBe(2) + expect(s.loadUint(256)).toBe(3) + const remaining = decode(s) + expect(remaining.loadUint(254)).toBe(4) + remaining.endParse() + }, +} + +const JustOverFullCell = { + build: (encode: RemainingEncoder): c.Cell => { + const b = c.beginCell() + b.storeUint(1, 256) + b.storeUint(2, 256) + b.storeUint(3, 256) + const payload = c.beginCell().storeUint(4, 255).endCell().beginParse() + encode(payload, b) + return b.endCell() + }, + load: (cell: c.Cell, decode: RemainingDecoder) => { + const s = cell.beginParse() + expect(s.loadUint(256)).toBe(1) + expect(s.loadUint(256)).toBe(2) + expect(s.loadUint(256)).toBe(3) + const remaining = decode(s) + expect(remaining.loadUint(255)).toBe(4) + remaining.endParse() + }, +} + +const InlinedWithReference = { + build: (encode: RemainingEncoder): c.Cell => { + const b = c.beginCell() + b.storeUint(1, 256) + b.storeUint(2, 256) + b.storeUint(3, 256) + const payload = c + .beginCell() + .storeUint(12, 254) + .storeRef(c.beginCell().storeUint(34, 256).endCell()) + .endCell() + .beginParse() + encode(payload, b) + return b.endCell() + }, + load: (cell: c.Cell, decode: RemainingDecoder) => { + const s = cell.beginParse() + expect(s.loadUint(256)).toBe(1) + expect(s.loadUint(256)).toBe(2) + expect(s.loadUint(256)).toBe(3) + const remaining = decode(s) + expect(remaining.loadUint(254)).toBe(12) + const refSlice = remaining.loadRef().beginParse() + remaining.endParse() + expect(refSlice.loadUint(256)).toBe(34) + refSlice.endParse() + }, +} + +const TooManyReferencesToInline = { + build: (encode: RemainingEncoder): c.Cell => { + const b = c.beginCell() + b.storeRef(c.beginCell().storeUint(1, 256).endCell()) + b.storeRef(c.beginCell().storeUint(2, 256).endCell()) + b.storeRef(c.beginCell().storeUint(3, 256).endCell()) + const payload = c + .beginCell() + .storeRef(c.beginCell().storeUint(11, 256).endCell()) + .storeRef(c.beginCell().storeUint(12, 256).endCell()) + .storeRef(c.beginCell().storeUint(13, 256).endCell()) + .storeRef(c.beginCell().storeUint(14, 256).endCell()) + .endCell() + .beginParse() + encode(payload, b) + return b.endCell() + }, + load: (cell: c.Cell, decode: RemainingDecoder) => { + const s = cell.beginParse() + const loadUintRef = (s: c.Slice) => { + const r = s.loadRef().beginParse() + const val = r.loadUint(256) + r.endParse() + return val + } + expect(loadUintRef(s)).toBe(1) + expect(loadUintRef(s)).toBe(2) + expect(loadUintRef(s)).toBe(3) + const remaining = decode(s) + expect(loadUintRef(remaining)).toBe(11) + expect(loadUintRef(remaining)).toBe(12) + expect(loadUintRef(remaining)).toBe(13) + expect(loadUintRef(remaining)).toBe(14) + remaining.endParse() + }, +} + +describe('RemainingBitsOrRef Unit Tests', () => { + let wrapper: s.SandboxContract + let blockchain: s.Blockchain + + beforeAll(async () => { + blockchain = await s.Blockchain.create() + const init = { + code: await contractCode.ccip.local('test.lib.RemainingBitsOrRef'), + data: c.Cell.EMPTY, + } + + wrapper = blockchain.openContract( + new tw.RemainingBitsOrRefTestWrapper(c.contractAddress(0, init), init), + ) + const deployer = await blockchain.treasury('deployer') + + await wrapper.sendDeploy(deployer.getSender(), c.toNano('0.05')) + }) + + describe('Tolk encoding uses inline or ref as expected', () => { + it('FullCell payload is stored inline', async () => { + const cell = await wrapper.getTestFullCell() + FullCell.load(cell, inlined.load) + }) + + it('JustOverFullCell payload is stored as a reference', async () => { + const cell = await wrapper.getTestJustOverFullCell() + JustOverFullCell.load(cell, ref.load) + }) + + it('InlinedWithReference payload is stored inline', async () => { + const cell = await wrapper.getTestInlinedWithReference() + InlinedWithReference.load(cell, inlined.load) + }) + + it('TooManyReferencesToInline payload is stored as a reference', async () => { + const cell = await wrapper.getTestTooManyReferencesToInline() + TooManyReferencesToInline.load(cell, ref.load) + }) + }) + + describe('TS codec produces cells equal to Tolk', () => { + it('FullCell', async () => { + const tolkCell = await wrapper.getTestFullCell() + const tsCell = FullCell.build(remainingBitsOrRefCodec.encode) + expect(tsCell.equals(tolkCell)).toBe(true) + FullCell.load(tsCell, remainingBitsOrRefCodec.load) + }) + + it('JustOverFullCell', async () => { + const tolkCell = await wrapper.getTestJustOverFullCell() + const tsCell = JustOverFullCell.build(remainingBitsOrRefCodec.encode) + expect(tsCell.equals(tolkCell)).toBe(true) + JustOverFullCell.load(tsCell, remainingBitsOrRefCodec.load) + }) + + it('InlinedWithReference', async () => { + const tolkCell = await wrapper.getTestInlinedWithReference() + const tsCell = InlinedWithReference.build(remainingBitsOrRefCodec.encode) + expect(tsCell.equals(tolkCell)).toBe(true) + InlinedWithReference.load(tsCell, remainingBitsOrRefCodec.load) + }) + + it('TooManyReferencesToInline', async () => { + const tolkCell = await wrapper.getTestTooManyReferencesToInline() + const tsCell = TooManyReferencesToInline.build(remainingBitsOrRefCodec.encode) + expect(tsCell.equals(tolkCell)).toBe(true) + TooManyReferencesToInline.load(tsCell, remainingBitsOrRefCodec.load) + }) + }) +}) diff --git a/contracts/wrappers/ccip/OnRamp.ts b/contracts/wrappers/ccip/OnRamp.ts index 67cc76628..11a805b4e 100644 --- a/contracts/wrappers/ccip/OnRamp.ts +++ b/contracts/wrappers/ccip/OnRamp.ts @@ -16,6 +16,7 @@ import { import { crc32 } from 'zlib' import { errorCode, facilityId, CellCodec } from '../utils' +import * as remainingBitsOrRef from '../libraries/utils/RemainingBitsOrRef' import * as ownable2step from '../libraries/access/Ownable2Step' import * as withdrawable from '../libraries/funding/Withdrawable' import { asSnakedCell, fromSnakeData } from '../../src/utils' @@ -292,12 +293,14 @@ export const builder = (() => { const getValidatedFeeContext: CellCodec = { encode: function (data: GetValidatedFeeContext): Builder { - return beginCell().storeAddress(data.onrampContext).storeSlice(data.userContext) + const b = beginCell().storeAddress(data.onrampContext) + remainingBitsOrRef.builder.encode(data.userContext, b) + return b }, load: function (src: Slice): GetValidatedFeeContext { return { onrampContext: src.loadAddress(), - userContext: src, + userContext: remainingBitsOrRef.builder.load(src), } }, } diff --git a/contracts/wrappers/ccip/Router.ts b/contracts/wrappers/ccip/Router.ts index 19118aabb..b6150dba7 100644 --- a/contracts/wrappers/ccip/Router.ts +++ b/contracts/wrappers/ccip/Router.ts @@ -18,6 +18,7 @@ import { errorCode, facilityId, CellCodec } from '../utils' import { asSnakedCell, asSnakeDataUint, fromSnakeData } from '../../src/utils' import { contractCode } from '../codeLoader' +import * as remainingBitsOrRef from '../libraries/utils/RemainingBitsOrRef' import * as ownable2step from '../libraries/access/Ownable2Step' import * as withdrawable from '../libraries/funding/Withdrawable' import * as upgradeable from '../libraries/versioning/Upgradeable' @@ -868,16 +869,17 @@ export const builder = (() => { const getValidatedFee: CellCodec = { encode: function (data: GetValidatedFee): Builder { - return beginCell() + const b = beginCell() .storeUint(opcodes.in.getValidatedFee, 32) .storeRef(ccipSend.encode(data.msg)) - .storeSlice(data.context) + remainingBitsOrRef.builder.encode(data.context, b) + return b }, load: function (src: Slice): GetValidatedFee { src.skip(32) return { msg: ccipSend.load(src.loadRef().beginParse()), - context: src, + context: remainingBitsOrRef.builder.load(src), } }, } diff --git a/contracts/wrappers/gen/ccip/OnRamp.ts b/contracts/wrappers/gen/ccip/OnRamp.ts index 4cf96d8fe..262711c80 100644 --- a/contracts/wrappers/gen/ccip/OnRamp.ts +++ b/contracts/wrappers/gen/ccip/OnRamp.ts @@ -427,11 +427,6 @@ export const Ownable2Step_OwnershipTransferred = { */ export type SnakedCell = c.Cell -/** - > type RemainingBitsOrRef = T - */ -export type RemainingBitsOrRef = T - /** > struct (0x0aa811ed) Upgradeable_Upgrade { > queryId: uint64 @@ -2197,6 +2192,11 @@ export const OnRamp_WithdrawFeeTokens = { } } +/** + > type RemainingBitsOrRef = T + */ +export type RemainingBitsOrRef = T + // ———————————————————————————————————————————— // class OnRamp // @@ -2236,7 +2236,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class OnRamp implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, diff --git a/contracts/wrappers/gen/ccip/Router.ts b/contracts/wrappers/gen/ccip/Router.ts index 104e45aa9..eec7ad5ca 100644 --- a/contracts/wrappers/gen/ccip/Router.ts +++ b/contracts/wrappers/gen/ccip/Router.ts @@ -482,11 +482,6 @@ export const Ownable2Step_OwnershipTransferred = { */ export type SnakedCell = c.Cell -/** - > type RemainingBitsOrRef = T - */ -export type RemainingBitsOrRef = T - /** > struct (0x0aa811ed) Upgradeable_Upgrade { > queryId: uint64 @@ -2504,6 +2499,11 @@ export const TokenAmount = { } } +/** + > type RemainingBitsOrRef = T + */ +export type RemainingBitsOrRef = T + // ———————————————————————————————————————————— // class Router // @@ -2543,7 +2543,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class Router implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, diff --git a/contracts/wrappers/gen/test/Test_RemainingBitsOrRef.ts b/contracts/wrappers/gen/test/Test_RemainingBitsOrRef.ts new file mode 100644 index 000000000..fec620566 --- /dev/null +++ b/contracts/wrappers/gen/test/Test_RemainingBitsOrRef.ts @@ -0,0 +1,206 @@ +// AUTO-GENERATED, do not edit +// It's a TypeScript wrapper for a RemainingBitsOrRefTestWrapper contract in Tolk. +/* eslint-disable */ + +import * as c from '@ton/core'; +import { beginCell, ContractProvider, Sender, SendMode } from '@ton/core'; + +// ———————————————————————————————————————————— +// predefined types and functions +// + +type StoreCallback = (obj: T, b: c.Builder) => void +type LoadCallback = (s: c.Slice) => T + +export type CellRef = { + ref: T +} + +function makeCellFrom(self: T, storeFn_T: StoreCallback): c.Cell { + let b = beginCell(); + storeFn_T(self, b); + return b.endCell(); +} + +function loadAndCheckPrefix32(s: c.Slice, expected: number, structName: string): void { + let prefix = s.loadUint(32); + if (prefix !== expected) { + throw new Error(`Incorrect prefix for '${structName}': expected 0x${expected.toString(16).padStart(8, '0')}, got 0x${prefix.toString(16).padStart(8, '0')}`); + } +} + +function lookupPrefix(s: c.Slice, expected: number, prefixLen: number): boolean { + return s.remainingBits >= prefixLen && s.preloadUint(prefixLen) === expected; +} + +function throwNonePrefixMatch(fieldPath: string): never { + throw new Error(`Incorrect prefix for '${fieldPath}': none of variants matched`); +} + +function storeCellRef(cell: CellRef, b: c.Builder, storeFn_T: StoreCallback): void { + let b_ref = c.beginCell(); + storeFn_T(cell.ref, b_ref); + b.storeRef(b_ref.endCell()); +} + +function loadCellRef(s: c.Slice, loadFn_T: LoadCallback): CellRef { + let s_ref = s.loadRef().beginParse(); + return { ref: loadFn_T(s_ref) }; +} + +function storeTolkNullable(v: T | null, b: c.Builder, storeFn_T: StoreCallback): void { + if (v === null) { + b.storeUint(0, 1); + } else { + b.storeUint(1, 1); + storeFn_T(v, b); + } +} + +// ———————————————————————————————————————————— +// parse get methods result from a TVM stack +// + +class StackReader { + constructor(private tuple: c.TupleItem[]) { + } + + static fromGetMethod(expectedN: number, getMethodResult: { stack: c.TupleReader }): StackReader { + let tuple = [] as c.TupleItem[]; + while (getMethodResult.stack.remaining) { + tuple.push(getMethodResult.stack.pop()); + } + if (tuple.length !== expectedN) { + throw new Error(`expected ${expectedN} stack width, got ${tuple.length}`); + } + return new StackReader(tuple); + } + + private popExpecting(itemType: string): ItemT { + const item = this.tuple.shift(); + if (item?.type === itemType) { + return item as ItemT; + } + throw new Error(`not '${itemType}' on a stack`); + } + + private popCellLike(): c.Cell { + const item = this.tuple.shift(); + if (item && (item.type === 'cell' || item.type === 'slice' || item.type === 'builder')) { + return item.cell; + } + throw new Error(`not cell/slice on a stack`); + } + + readBigInt(): bigint { + return this.popExpecting('int').value; + } + + readBoolean(): boolean { + return this.popExpecting('int').value !== 0n; + } + + readCell(): c.Cell { + return this.popCellLike(); + } + + readSlice(): c.Slice { + return this.popCellLike().beginParse(); + } +} + +// ———————————————————————————————————————————— +// auto-generated serializers to/from cells +// + +type coins = bigint + +// ———————————————————————————————————————————— +// class RemainingBitsOrRefTestWrapper +// + +interface ExtraSendOptions { + bounce?: boolean // default: false + sendMode?: SendMode // default: SendMode.PAY_GAS_SEPARATELY + extraCurrencies?: c.ExtraCurrency // default: empty dict +} + +interface DeployedAddrOptions { + workchain?: number // default: 0 (basechain) + toShard?: { fixedPrefixLength: number; closeTo: c.Address } + overrideContractCode?: c.Cell +} + +function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedAddrOptions): c.Address { + const stateInitCell = beginCell().store(c.storeStateInit({ + code, + data, + splitDepth: options.toShard?.fixedPrefixLength, + special: null, + libraries: null, + })).endCell(); + + let addrHash = stateInitCell.hash(); + if (options.toShard) { + const shardDepth = options.toShard.fixedPrefixLength; + addrHash = beginCell() + .storeBits(new c.BitString(options.toShard.closeTo.hash, 0, shardDepth)) + .storeBits(new c.BitString(stateInitCell.hash(), shardDepth, 256 - shardDepth)) + .endCell() + .beginParse().loadBuffer(32); + } + + return new c.Address(options.workchain ?? 0, addrHash); +} + +export class RemainingBitsOrRefTestWrapper implements c.Contract { + static CodeCell = c.Cell.fromBase64('te6ccgECDAEAAWQAART/APSkE/S88sgLAQIBYgIDABjQ+JHyQIQPAccA8vQCASAEBQIDnkQGBwIBIAgJAA27ZxyMv/yYALvdxyMv/yXLIy//Jc8jL/8lxyMv/yXLIy//Jc8jL/8l0yMv/yQbIzBXME8wByMwSzBLMEszJINDXS4QJJM8xoXQlzzKhA6S5klt/k7nDAOKUAc+DzJcBz4EB0M8W4smAgFqCgsAi7oduAIsjL/8lxyMv/cs8L/3PPC/+ADMjL/RLMySDQ10uECSTPMaF0Jc8yoQOkuZJbf5O5wwDilAHPg8yXAc+BAdDPFuLJgAea9EuORl/7lnhf+554X/umRl/2SQaGulwgSSZ5jQuhLnmVCB0lzJLb/J3OGAcUoA58HmS4DnwIDoZ4txZMAAea+auORl/7lnhf+554X/umRl/uSQaGulwgSSZ5jQuhLnmVCB0lzJLb/J3OGAcUoA58HmS4DnwIDoZ4txZMA='); + + static Errors = { + } + + readonly address: c.Address + readonly init: { code: c.Cell, data: c.Cell } | undefined + + constructor(address: c.Address, init?: { code: c.Cell, data: c.Cell }) { + this.address = address; + this.init = init; + } + + static fromAddress(address: c.Address) { + return new RemainingBitsOrRefTestWrapper(address); + } + + async sendDeploy(provider: ContractProvider, via: Sender, msgValue: coins, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: c.Cell.EMPTY, + ...extraOptions + }); + } + + async getTestIncompleteCell(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('test_incomplete_cell', [])); + return r.readCell(); + } + + async getTestFullCell(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('test_full_cell', [])); + return r.readCell(); + } + + async getTestJustOverFullCell(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('test_just_over_full_cell', [])); + return r.readCell(); + } + + async getTestInlinedWithReference(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('test_inlined_with_reference', [])); + return r.readCell(); + } + + async getTestTooManyReferencesToInline(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('test_too_many_references_to_inline', [])); + return r.readCell(); + } +} diff --git a/contracts/wrappers/libraries/utils/RemainingBitsOrRef.ts b/contracts/wrappers/libraries/utils/RemainingBitsOrRef.ts new file mode 100644 index 000000000..3e38f963d --- /dev/null +++ b/contracts/wrappers/libraries/utils/RemainingBitsOrRef.ts @@ -0,0 +1,32 @@ +import * as c from '@ton/core' + +export type RemainingBitsOrRef = c.Slice + +// This is the codec for RemainingBitsOrRef type in Tolk +// It allows storing/loading a Slice either directly as bits or as a reference +// to a cell, depending on available space. +// It has a different interface than the usual CellCodec because it needs +// to access the Builder instance to check available bits. +export const builder = { + encode: function (data: RemainingBitsOrRef, b: c.Builder) { + const availableBits = 1023 - b.bits + const availableRefs = 4 - b.refs + if (availableBits < data.remainingBits + 1 || availableRefs < data.remainingRefs) { + // not enough space, create a new cell + b.storeMaybeRef(data.asCell()) + } else { + // can be inlined + b.storeBit(false) + b.storeSlice(data) + } + }, + load: function (src: c.Slice) { + const ref = src.loadMaybeRef() + if (ref) { + src.endParse() + return ref.beginParse() + } else { + return src + } + }, +} diff --git a/contracts/wrappers/test.lib.RemainingBitsOrRef.compile.ts b/contracts/wrappers/test.lib.RemainingBitsOrRef.compile.ts new file mode 100644 index 000000000..d776cbb3d --- /dev/null +++ b/contracts/wrappers/test.lib.RemainingBitsOrRef.compile.ts @@ -0,0 +1,7 @@ +import { CompilerConfig } from '@ton/blueprint' + +export const compile: CompilerConfig = { + lang: 'tolk', + entrypoint: 'contracts/test/lib/remaining_bits_or_ref.tolk', + withStackComments: true, +} diff --git a/contracts/wrappers/utils.ts b/contracts/wrappers/utils.ts index bf89c1448..9cc709f61 100644 --- a/contracts/wrappers/utils.ts +++ b/contracts/wrappers/utils.ts @@ -34,30 +34,3 @@ export interface StackCodec { encode: (data: T) => TupleItem[] load: (src: TupleItem[]) => T } - -// This is the codec for RemainingBitsOrRef type in Tolk -// It allows storing/loading a Slice either directly as bits or as a reference -// to a cell, depending on available space. -// It has a different interface than the usual CellCodec because it needs -// to access the Builder instance to check available bits. -export const remainingBitsOrRefCodec = { - encode: function (data: Slice, b: Builder) { - const nBits = data.remainingBits - if (b.availableBits < nBits - 1) { - b.storeBit(1) // ref - b.storeRef(data.asCell()) - } else { - b.storeBit(0) // bits - b.storeSlice(data) - } - }, - load: function (src: Slice): Slice { - const isRef = src.loadBit() - if (isRef) { - const ref = src.loadRef() - return ref.beginParse() - } else { - return src - } - }, -}