Skip to content

Commit f6e0387

Browse files
committed
feat: handle code with a single exotic cell, now we load actual code and return it along with originalCodeCell
1 parent 4bd819e commit f6e0387

File tree

5 files changed

+87
-62
lines changed

5 files changed

+87
-62
lines changed

src/methods.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,38 +291,43 @@ export const getLibraryByHash = async (testnet: boolean, hash: string): Promise<
291291
* @param account Current {@link ShardAccount} snapshot.
292292
* @param tx Transaction whose `inMessage` may include `Init`.
293293
* @returns Serialized dict cell or `undefined`
294-
* when no libraries are referenced.
294+
* when no libraries are referenced and actual code cell if
295+
* original code is just an exotic library cell
295296
*/
296297
export const collectUsedLibraries = async (
297298
testnet: boolean,
298299
account: ShardAccount,
299300
tx: Transaction,
300-
): Promise<Cell | undefined> => {
301+
): Promise<[Cell | undefined, Cell | undefined]> => {
301302
const libs = Dictionary.empty(Dictionary.Keys.BigUint(256), Dictionary.Values.Cell())
302303

303-
const addMaybeExoticLibrary = async (code: Cell | undefined): Promise<void> => {
304+
const addMaybeExoticLibrary = async (code: Cell | undefined): Promise<Cell | undefined> => {
304305
const EXOTIC_LIBRARY_TAG = 2
305-
if (code === undefined) return
306-
if (code.bits.length !== 256 + 8) return // not an exotic library cell
306+
if (code === undefined) return undefined
307+
if (code.bits.length !== 256 + 8) return undefined // not an exotic library cell
307308

308309
const cs = code.beginParse(true) // allow exotics
309310
const tag = cs.loadUint(8)
310-
if (tag !== EXOTIC_LIBRARY_TAG) return // not a library cell
311+
if (tag !== EXOTIC_LIBRARY_TAG) return undefined // not a library cell
311312

312313
const libHash = cs.loadBuffer(32)
313314
const libHashHex = libHash.toString("hex").toUpperCase()
314315
const actualCode = await getLibraryByHash(testnet, libHashHex)
315316
libs.set(BigInt(`0x${libHashHex}`), actualCode)
317+
return actualCode
316318
}
317319

320+
// if current contract code is exotic cell, we want to return actual code to the user
321+
let loadedCellCode: Cell | undefined = undefined
322+
318323
// 1. scan the *current* contract code for exotic‑library links
319324
const state = account.account?.storage.state
320325
if (state?.type === "active") {
321326
// The contract is already deployed and “active” so its `code`
322327
// cell may itself be a 264‑bit exotic library reference (tag 2).
323328
// If that’s the case, download the real library code and
324329
// register it in the `libs` dictionary.
325-
await addMaybeExoticLibrary(state.state.code ?? undefined)
330+
loadedCellCode = await addMaybeExoticLibrary(state.state.code ?? undefined)
326331
}
327332

328333
// 2. scan the *incoming StateInit* (if present)
@@ -337,10 +342,10 @@ export const collectUsedLibraries = async (
337342
}
338343

339344
// no libs found, return undefined, for emulator this means no libraries
340-
if (libs.size === 0) return undefined
345+
if (libs.size === 0) return [undefined, loadedCellCode]
341346

342347
// emulator expects libraries as a Cell with immediate dictionary
343-
return beginCell().storeDictDirect(libs).endCell()
348+
return [beginCell().storeDictDirect(libs).endCell(), loadedCellCode]
344349
}
345350

346351
/**

src/runner.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const retrace = async (testnet: boolean, txLink: string): Promise<TraceRe
8888
// retrieve block config to pass it to emulator
8989
const blockConfig = await getBlockConfig(testnet, fullBlock)
9090
const shardAccountBeforeTx = await getBlockAccount(testnet, baseTx.address, fullBlock)
91-
const libs = await collectUsedLibraries(testnet, shardAccountBeforeTx, tx.tx)
91+
const [libs, loadedCode] = await collectUsedLibraries(testnet, shardAccountBeforeTx, tx.tx)
9292

9393
// retrieve code cell if account in active mode
9494
const state = shardAccountBeforeTx.account?.storage.state
@@ -132,7 +132,8 @@ export const retrace = async (testnet: boolean, txLink: string): Promise<TraceRe
132132

133133
return {
134134
stateUpdateHashOk,
135-
codeCell,
135+
codeCell: loadedCode ?? codeCell,
136+
originalCodeCell: codeCell,
136137
inMsg: {
137138
sender,
138139
contract,

src/test/__snapshots__/test.spec.ts.snap

Lines changed: 62 additions & 50 deletions
Large diffs are not rendered by default.

src/test/test.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ describe("transactions", () => {
9191
function checkResult(res: TraceResult, expectedOk: boolean = true): void {
9292
expect(res.stateUpdateHashOk).toEqual(expectedOk)
9393
expect(res.codeCell?.toBoc().toString("hex")).toMatchSnapshot()
94+
expect(res.originalCodeCell?.toBoc().toString("hex")).toMatchSnapshot()
9495
expect(res.inMsg.sender?.toString()).toMatchSnapshot()
9596
expect(res.inMsg.contract.toString()).toMatchSnapshot()
9697
expect(res.inMsg.amount).toMatchSnapshot()

src/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,15 @@ export interface TraceResult {
322322
*/
323323
stateUpdateHashOk: boolean
324324
/**
325-
* Code of an account before transaction
325+
* Code of an account before transaction. If code is just an exotic cell,
326+
* this field will contain actual library code, see {@link originalCodeCell}
327+
* if you need original code cell.
326328
*/
327329
codeCell: Cell | undefined
330+
/**
331+
* Code of an account before transaction
332+
*/
333+
originalCodeCell: Cell | undefined
328334
/**
329335
* Information about in-message
330336
*/

0 commit comments

Comments
 (0)