Skip to content

Commit

Permalink
refactor: optimize readForwardFee stdlib function (tact-lang#1614)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shvandre authored Jan 29, 2025
1 parent 760ce43 commit c64a6c0
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 29 deletions.
7 changes: 3 additions & 4 deletions src/stdlib/stdlib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,9 @@ files["std/config.tact"] =
files["std/context.tact"] =
"c3RydWN0IENvbnRleHQgewogICAgYm91bmNlZDogQm9vbDsKICAgIHNlbmRlcjogQWRkcmVzczsKICAgIHZhbHVlOiBJbnQ7CiAgICByYXc6IFNsaWNlOwp9CgpAbmFt" +
"ZShfX3RhY3RfY29udGV4dF9nZXQpCm5hdGl2ZSBjb250ZXh0KCk6IENvbnRleHQ7CgpAbmFtZShfX3RhY3RfY29udGV4dF9nZXRfc2VuZGVyKQpuYXRpdmUgc2VuZGVy" +
"KCk6IEFkZHJlc3M7CgpleHRlbmRzIGZ1biByZWFkRm9yd2FyZEZlZShzZWxmOiBDb250ZXh0KTogSW50IHsKICAgIGxldCBzYzogU2xpY2UgPSBzZWxmLnJhdzsKICAg" +
"IHNjLmxvYWRBZGRyZXNzKCk7IC8vIFNraXAgZGVzdGluYXRpb24KICAgIHNjLmxvYWRDb2lucygpOyAvLyBTa2lwIHZhbHVlCiAgICBzYy5za2lwQml0cygxKTsgLy8g" +
"U2tpcCBleHRyYSBjdXJyZW5jeSBjb2xsZWN0aW9uCiAgICBzYy5sb2FkQ29pbnMoKTsgLy8gU2tpcCBpaHJfZmVlCiAgICByZXR1cm4gKHNjLmxvYWRDb2lucygpICog" +
"MykgLyAyOwp9";
"KCk6IEFkZHJlc3M7Cgphc20gZXh0ZW5kcyBmdW4gcmVhZEZvcndhcmRGZWUoc2VsZjogQ29udGV4dCk6IEludCB7CiAgICBMRE1TR0FERFIKICAgIExER1JBTVMKICAg" +
"IE9ORQogICAgU0RTS0lQRklSU1QKICAgIExER1JBTVMKICAgIExER1JBTVMKICAgIERST1AKICAgIDYgMSBCTEtEUk9QMgogICAgWkVSTwogICAgR0VUT1JJR0lOQUxG" +
"V0RGRUUKfQ==";
files["std/contract.tact"] =
"c3RydWN0IFN0YXRlSW5pdCB7CiAgICBjb2RlOiBDZWxsOwogICAgZGF0YTogQ2VsbDsKfQoKQG5hbWUoX190YWN0X2NvbXB1dGVfY29udHJhY3RfYWRkcmVzcykKbmF0" +
"aXZlIGNvbnRyYWN0QWRkcmVzc0V4dChjaGFpbjogSW50LCBjb2RlOiBDZWxsLCBkYXRhOiBDZWxsKTogQWRkcmVzczsKCmlubGluZSBmdW4gY29udHJhY3RBZGRyZXNz" +
Expand Down
18 changes: 11 additions & 7 deletions src/stdlib/stdlib/std/context.tact
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ native context(): Context;
@name(__tact_context_get_sender)
native sender(): Address;

extends fun readForwardFee(self: Context): Int {
let sc: Slice = self.raw;
sc.loadAddress(); // Skip destination
sc.loadCoins(); // Skip value
sc.skipBits(1); // Skip extra currency collection
sc.loadCoins(); // Skip ihr_fee
return (sc.loadCoins() * 3) / 2;
asm extends fun readForwardFee(self: Context): Int {
LDMSGADDR
LDGRAMS
ONE
SDSKIPFIRST
LDGRAMS
LDGRAMS
DROP
6 1 BLKDROP2
ZERO
GETORIGINALFWDFEE
}
52 changes: 38 additions & 14 deletions src/test/benchmarks/benchmarks.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import {
beginCell,
toNano,
TransactionComputeVm,
TransactionDescriptionGeneric,
} from "@ton/core";
import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";
import {
Blockchain,
BlockchainTransaction,
SandboxContract,
TreasuryContract,
} from "@ton/sandbox";
import { Functions } from "./contracts/output/benchmark_functions_Functions";
import { Functions as FunctionsInline } from "./contracts/output/benchmark_functions_inline_Functions";
import "@ton/test-utils";

function measureGas(txs: BlockchainTransaction[]) {
return (
(txs[1]!.description as TransactionDescriptionGeneric)
.computePhase as TransactionComputeVm
).gasUsed;
}

describe("benchmarks", () => {
let blockchain: Blockchain;
let treasure: SandboxContract<TreasuryContract>;
Expand All @@ -27,17 +40,13 @@ describe("benchmarks", () => {
{ $$type: "Add", value: 10n },
);

const gasUsed = (
(
sendResult.transactions[1]!
.description as TransactionDescriptionGeneric
).computePhase as TransactionComputeVm
).gasUsed;
const gasUsed = measureGas(sendResult.transactions);

expect(gasUsed).toMatchInlineSnapshot(`2869n`);

// Verify code size
const codeSize = functions.init!.code.toBoc().length;
expect(codeSize).toMatchInlineSnapshot(`227`);
expect(codeSize).toMatchInlineSnapshot(`283`);
});

it("benchmark functions (inline)", async () => {
Expand All @@ -51,16 +60,31 @@ describe("benchmarks", () => {
{ $$type: "Add", value: 10n },
);

const gasUsed = (
(
sendResult.transactions[1]!
.description as TransactionDescriptionGeneric
).computePhase as TransactionComputeVm
).gasUsed;
const gasUsed = measureGas(sendResult.transactions);
expect(gasUsed).toMatchInlineSnapshot(`2738n`);

// Verify code size
const codeSize = functionsInline.init!.code.toBoc().length;
expect(codeSize).toMatchInlineSnapshot(`220`);
});
it("benchmark readFwdFee", async () => {
const testContract = blockchain.openContract(
await Functions.fromInit(),
);
const sendResult = await testContract.send(
treasure.getSender(),
{ value: toNano(1) },
{
$$type: "TestGetFwdFee",
any: beginCell()
.storeUint(0, 32)
.storeStringTail("This is test payload")
.asSlice(),
},
);
const gasUsed = measureGas(sendResult.transactions);
expect(gasUsed).toMatchInlineSnapshot(`3283n`);
const codeSize = testContract.init!.code.toBoc().length;
expect(codeSize).toMatchInlineSnapshot(`283`);
});
});
13 changes: 12 additions & 1 deletion src/test/benchmarks/contracts/benchmark_functions.tact
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ message Sub {
value: Int;
}

message TestGetFwdFee {
any: Slice;
}

asm fun touch(x: Int) {
NOP
}

contract Functions {
value: Int;

Expand All @@ -26,4 +34,7 @@ contract Functions {
require(msg.value > 0, "Value must be greater than 0");
self.update(-msg.value);
}
}
receive(msg: TestGetFwdFee) {
touch(context().readForwardFee());
}
}
12 changes: 12 additions & 0 deletions src/test/e2e-emulated/contracts/stdlib.tact
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,16 @@ contract StdlibTest {
get fun parseVarAddress(slice: Slice): VarAddress {
return parseVarAddress(slice);
}

get fun parseOriginalFwdFee(msg: Slice): Int {
msg.skipBits(4); //Skip tags
msg.loadAddress(); // Skip source
let ctx: Context = Context{
bounced: false,
sender: myAddress(),
value: ton("1"),
raw: msg
};
return ctx.readForwardFee();
}
}
13 changes: 10 additions & 3 deletions src/test/e2e-emulated/stdlib.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Address, beginCell, toNano } from "@ton/core";
import { Address, beginCell, Cell, toNano } from "@ton/core";
import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";
import { StdlibTest } from "./contracts/output/stdlib_StdlibTest";
import "@ton/test-utils";
Expand Down Expand Up @@ -55,8 +55,7 @@ describe("stdlib", () => {
.endCell()
.toString(),
).toBe(beginCell().storeBit(true).endCell().toString());

expect(await contract.getTvm_2023_07Upgrade()).toEqual(1289n); // gas consumed
expect(await contract.getTvm_2023_07Upgrade()).toEqual(1389n); // gas consumed
expect(await contract.getTvm_2024_04Upgrade()).toEqual(82009144n);

expect(
Expand Down Expand Up @@ -106,5 +105,13 @@ describe("stdlib", () => {
expect(addrVar.address.asCell()).toEqualCell(
beginCell().storeUint(345, 123).endCell(),
);

const RandomMessage = Cell.fromBase64(
"te6ccuEBAQEAZwDOAMloAdbATUBllK0egYWU34F08lIun9zBwyu7UZQrueKKJgnXADfmsDtWQP5D/YkXX+XlULvs4HivRaKY38ftT2hS5yAAEE1v+YAGCCNaAABhF0kRG4TPMTmAapk7bYAAGEXSDt8BwKQrvKE=",
);
const res = await contract.getParseOriginalFwdFee(
RandomMessage.beginParse(),
);
expect(res).toBe(400000n);
});
});

0 comments on commit c64a6c0

Please sign in to comment.