Skip to content

Commit

Permalink
fix: contract method calls in return statements (#829)
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-trunov authored Sep 15, 2024
1 parent 897b480 commit 82fec48
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Return-statements in `init()` function do not cause FunC compilation error anymore: PR [#794](https://github.com/tact-lang/tact/pull/794)
- `emptyMap()` in equality comparison expressions does not cause code generation failures: PR [#814](https://github.com/tact-lang/tact/pull/814)
- Maps with `coins` as value type are now correctly handled in structs: PR [#821](https://github.com/tact-lang/tact/pull/821)
- Contract method calls in return statements: PR [#829](https://github.com/tact-lang/tact/pull/829)

## [1.4.4] - 2024-08-18

Expand Down
9 changes: 8 additions & 1 deletion src/generator/writers/writeFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,14 @@ export function writeStatement(

// Return
if (self) {
ctx.append(`return (${self}, ${result});`);
// we introduce an intermediate return variable here
// to treat the case of a contract method call which
// can modify "self", otherwise the "self" below would
// contain the old state of contract, not the one
// updated in the "result" expression
const retVar = freshIdentifier("ret");
ctx.append(`var ${retVar} = ${result};`);
ctx.append(`return (${self}, ${retVar});`);
} else {
ctx.append(`return ${result};`);
}
Expand Down
32 changes: 32 additions & 0 deletions src/test/e2e-emulated/contract-methods.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { toNano } from "@ton/core";
import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";
import { Test } from "./contracts/output/contract-methods_Test";
import "@ton/test-utils";

describe("contract-methods", () => {
let blockchain: Blockchain;
let treasure: SandboxContract<TreasuryContract>;
let contract: SandboxContract<Test>;

beforeEach(async () => {
blockchain = await Blockchain.create();
blockchain.verbosity.print = false;
treasure = await blockchain.treasury("treasure");

contract = blockchain.openContract(await Test.fromInit());

const deployResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
null,
);
expect(deployResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: true,
deploy: true,
});
});

it("should implement contract methods correctly", async () => {});
});
24 changes: 24 additions & 0 deletions src/test/e2e-emulated/contracts/contract-methods.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
contract Test {
flags: Int as uint256 = 0;
oneMoreVar: Int = 239;
receive() {
self.checkImmediateReturn();
require(self.flags == 42, "checkImmediateReturn() is mis-compiled");
self.flags = 0;
self.checkReturnViaLocalVar();
require(self.flags == 42, "checkReturnViaLocalVar() is mis-compiled");
}

fun checkImmediateReturn(): Bool {
return self.check();
}
fun checkReturnViaLocalVar(): Bool {
let foo = self.check();
return foo;
}
fun check(): Bool {
self.flags = 42;
return true;
}
}

5 changes: 5 additions & 0 deletions tact.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,11 @@
"name": "semantics",
"path": "./src/test/e2e-emulated/contracts/semantics.tact",
"output": "./src/test/e2e-emulated/contracts/output"
},
{
"name": "contract-methods",
"path": "./src/test/e2e-emulated/contracts/contract-methods.tact",
"output": "./src/test/e2e-emulated/contracts/output"
}
]
}

0 comments on commit 82fec48

Please sign in to comment.