Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Deployable #2002

Closed
anton-trunov opened this issue Feb 25, 2025 · 13 comments · Fixed by #2354
Closed

Deprecate Deployable #2002

anton-trunov opened this issue Feb 25, 2025 · 13 comments · Fixed by #2354
Assignees
Labels
kind: docs Documentation for docs.tact-lang.org kept in docs folder
Milestone

Comments

@anton-trunov
Copy link
Member

Related issues: #1868, #1964

@anton-trunov anton-trunov added the kind: docs Documentation for docs.tact-lang.org kept in docs folder label Feb 25, 2025
@anton-trunov anton-trunov added this to the Doc: 2025-02 milestone Feb 25, 2025
@novusnota
Copy link
Member

novusnota commented Feb 25, 2025

Hmm, can we simply make Deployable an empty binary receiver? What's the alternative for it, a null Cell?

Besides, queryId can still be useful some times, so with removal of usage of Deployable we better not mark it as deprecated. And the FactoryDeployable as well.

@novusnota novusnota added size: big This is a hard task, more like a project and will take a while to implement and removed size: big This is a hard task, more like a project and will take a while to implement labels Feb 25, 2025
@anton-trunov
Copy link
Member Author

Hmm, can we simply make Deployable an empty binary receiver? What's the alternative for it, a null Cell?

This will break existing user tests

@Kaladin13
Copy link
Contributor

I think we should offer alternative way to deploy contract right away in the docs and in the examples, maybe in form of new message type in generated wrappers, since it requires advanced knowledge of TON internals to know how stateInit and initial body and data in the contract interact with each other

We should have something like

const contract = blockchain.openContract(
            await Escrow.fromInit(
                seller.address,
            ),
        );

const deployResult = await contract.sendDeploy(
    deployer.getSender(),
    {
        value: toNano("0.1"),
    });

// Send deploy under the hood can be just simple empty send, something like
send({
        to: escrowAddress,
        value: toNano("0.05"),
        body: beginCell().endCell(),
        sendMode: SendMode.PAY_GAS_SEPARATELY,
    });

Since contract deployment is a hot topic for all new web3 developers, especially in TON, I think we should carefully think about the design

@novusnota
Copy link
Member

What about FactoryDeployable?

@Kaladin13
Copy link
Contributor

Can you expand on this please? You mean separate typescript class?

@novusnota
Copy link
Member

Can you expand on this please? You mean separate typescript class?

No, I meant https://docs.tact-lang.org/ref/stdlib-deploy/#factorydeployable.

Here's the @stdlib/deploy in our sources: https://github.com/tact-lang/tact/blob/main/src/stdlib/stdlib/libs/deploy.tact

@novusnota
Copy link
Member

novusnota commented Mar 3, 2025

I've got an idea — we place the following to @stdlib/deploy and then add the #2198 there as well:

trait EmptyDeployable {
    /// `null` message body receiver for deployment purposes
    receive() {}
}

trait CashbackDeployable {
    /// `null` message body receiver for deployment purposes
    /// Forwards the remaining value back to the sender
    receive() { cashback() }
}

UPD: Changed the NullDeployable to EmptyDeployable

@Kaladin13
Copy link
Contributor

That's good solution.

I will propose an offer to smoother dev experience. In case of this specific trait being enabled on contract, let's generate additional method in the wrapper, sendDeploy, that will encapsulate null deploy message to the contract. Same idea as in this reply, but it could be combined with @novusnota new trait propositions

@anton-trunov
Copy link
Member Author

trait NullDeployable {
...
}

trait NullDeployable {
...
}

@novusnota Did you mean EmptyDeployable and EmptyDeployableWithCashback?

@anton-trunov
Copy link
Member Author

instead of doing that import and using that trait I'd prefer to copy-paste receive() { cashback() } into my contracts

@anton-trunov
Copy link
Member Author

also, I think it makes sense to have a trait version with something like nativeReserve(self.RESERVED_FUNDS, ReserveAtMost)

@novusnota
Copy link
Member

The move to receive() should be supported by the Web IDE as per tact-lang/web-ide#213.

@novusnota
Copy link
Member

novusnota commented Mar 10, 2025

As a follow-up to my commment earlier, we might do the following:

  1. Add EmptyDeploy and CashbackDeploy message structs, both empty
  2. Add respective receivers
message EmptyDeploy {}
message CashbackDeploy {}

trait EmptyDeployable {
    /// Does not forward the remaining value back to the sender,
    /// simply deploys the contract and/or receives funds
    receive(_: EmptyDeploy) {}
}

trait CashbackDeployable {
    /// Forwards the remaining value back to the sender
    receive(_: CashbackDeploy) { cashback(sender()) }
}

I'm unsure if those would be cheaper than a null message body receive(). However, with this approach, the contract could inherit from both traits at the same time to allow different deployment strategies — in this case, they're about whether or not to do the cashback, but we could have something more sophisticated, like nativeReserve(self.RESERVED_FUNDS, ReserveAtMost) or something similar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: docs Documentation for docs.tact-lang.org kept in docs folder
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants