tact-lang / tact

Tact compiler main repository
https://tact-lang.org
MIT License
394 stars 111 forks source link

[Feature request] implement ability to store code of smart-contract in masterchain library #1013

Open imartemy1524 opened 2 weeks ago

imartemy1524 commented 2 weeks ago

The problem

Right now, when a smart contract uses sharding, it duplicates the code of all sharded items during deployment. This leads to high fees, especially when the smart contract code is large. These fees may be suitable when the number of sharded smart contracts is limited, but in the case of millions of jettons or NFTs, it requires the deployer to spend a significant amount on fees each time he deploys new smart-contract.

One possible solution for this is Library cell - when the code of smart-contract (it may be not only the code, but also some hardcoded constants) is stored in masterchain as a library and all children stores only its hash. Example of jetton, which releases this approach and stores library cell in this masterchain smart-contract

Possible solution

TACT

This is an example of the way I see it, feel free to disagree with me.

First of all, add possibility to "store" actual code of smart-contract as a library inside tact:

contract Parent{
    receive("deploy"){
        let data = initOf Child(self.id);
        // this code would refer to exotic cell, which is easy to build using actual code hash:
        // https://docs.ton.org/v3/documentation/data-formats/tlb/library-cells#using-in-tonton
        let code = data.code;
        self.forward(contractAddress(data), "init".asComment(), true, data);
    }
}
import "@stdlib/library"
// MasterchainLibrary from @stdlib/library trait converts contract to an exotic cell
contract Child with MasterchainLibrary{
    // for how much the default deploy script would store the library (can be extended) 
    override virtual const minStoringTime = 3600 * 24 * 30;
    init(id: Int){ }
    receive("init"){ }
}

Then replace code of all smart-contract, containing MasterchainLibrary with exotic cells:


let lib_prep = beginCell().storeUint(2,8).storeBuffer(jwallet_code_raw.hash()).endCell();
jwallet_code = new Cell({ exotic:true, bits: lib_prep.bits, refs:lib_prep.refs});

Typescript

Create exported function in typescript to store such library for testing purposes in TON emulator:

export function initializeLibraries(blockchain: Blockchain, codes: Cell[]) {
    const _libs = Dictionary.empty(Dictionary.Keys.BigUint(256), Dictionary.Values.Cell());
    for (const jwallet_code_raw of codes) {
        _libs.set(BigInt(`0x${jwallet_code_raw.hash().toString('hex')}`), jwallet_code_raw);
    }
    blockchain.libs = beginCell().storeDictDirect(_libs).endCell();
}

Or wait until @ton/sandbox would actually support it. (Maybe hardcode smart-contract code inside codes)

Create deployment library script, something like this, which would deploy all of libraries into the masterchain in one run. Also specify DEFAULT_DURATION for each library (an overriden constact in tact code).