Classes Realized on Deploying Good Contracts, Half 2
That is the second article in our collection on integrating fee channels on Telegram Open Community. Within the first half, we launched the community, detailed our expertise of the competition, and defined how synchronous and asynchronous good contracts work. As the subsequent addition to the collection, this text particulars how we constructed a synchronous fee channel on the community throughout TON’s contest again in September. Right here, we will probably be speaking solely about Fift (TON’s general-purpose programming language) and FunC (TON’s programming language for writing good contracts).
The TON white paper supplies extra in-depth details about fee channels, however we are going to briefly clarify them once more.
A synchronous fee channel permits sending transactions between two customers off-chain utilizing on-chain property. In our case — GRAMs. It’s inconceivable for one get together to cheat the opposite off-chain, and transactions are made a lot sooner than executing layer-one blockchain transactions, as solely consumer units are used to finish them with out having to put in writing to the blockchain. There are two fundamental operations: deposit and withdraw. The withdrawal is essentially the most difficult one to implement.
To make an accurate withdrawal, customers want to supply the newest details about the state of their channel. The state consists of the steps and digital signatures of every participant, which suggests it’s not potential to supply an accurate state with information that has not been accepted by each events.
To deploy a wise contract, you’ll want to write a deploy script in Fift and compile it to a .boc (bag of cells) file. Doing this makes a number of cells that will probably be linked to one another. GRAMs then have to be despatched to the tackle that was acquired throughout deploy script execution. As soon as GRAMs are on the tackle, ship the .boc file to the community and the contract will probably be deployed.
To make a perform name, write a script that may ship an exterior message to the deployed good contract.
Mainly, something on TON is a cell with some references. A bag of cells is a knowledge construction that was designed by the Telegram staff. It’s an actor mannequin. Extra particulars are at TON whitepaper: “all the things is a bag of cells.” You’re constructing a cell that may work together with one other cell when it’s deployed.
Every peer-to-peer fee channel is a single good contract. Let’s check out the segments of a wise contract.
A serialized Fift script is used to deploy a contract. It’s saved to a .boc file and despatched to the community through TON Cli, the community’s gentle consumer.
The newest cell on the stack is the results of executing the above Fift script.
The same old segments of a Fift deploy script embody (however should not restricted to):
- Code of the good contract as a single cell (normally written in FunC, then compiled into Fift ASM code and included in the principle .fif file utilizing path-to-compiled-asm.fif).
- Preliminary storage of the good contract (see beneath).
- New good contract tackle (the hash from the preliminary state of the good contract that additionally contains the good contract code cell and the preliminary storage cell).
- Arguments of the primary name of the recv_external perform (the quantity of arguments and sort relies on the contract).
- An exterior message cell for initialization, which will probably be serialized into bytes and packed to the .boc file, which consists of all the information from factors 1–four and a few further ones which can be nonetheless missing documentation.
When the .boc is compiled, a certain quantity of GRAMs have to be despatched to the good contract tackle. The .boc file should be despatched to the community to initialize the good contract. The quantity of GRAMs relies on the dimensions and quantity of calculations of the deployed good contract’s exterior message cell (not solely the code of it). Gasoline × gasoline value is taken from the deployed good contract steadiness. This quantity is the minimal wanted to pay for gasoline throughout the deployment.
A illustration of the storage:
- seqno 32 bits
- contract_status four bits
- first_user_pubkey. The primary get together’s public key 256 bits
- second_user_pubkey. The second get together’s public key 256 bits
- time_to_send. Time to ship after the very first state being submitted 32 bits (legitimate till 2038)
- depositSum. The deposited sum of two contributors as much as 121 bits
- state_num 64 bits. The present quantity of states that occurred
A cell incorporates as much as 1023 bits and 4 references to different cells. We had been capable of match the whole storage onto one cell with out a single reference. Our storage can take up a most of 765 bits.
All good contract states
0x0 — Deployment state
0x1 — Channel opened and prepared for deposit
0x2 — Deposit by consumer 1
0x3 — Deposit by consumer 2
0x4 — The deposit is blocked. It’s potential to supply a state to the good contract
0x5 — Person 1 has offered the state
0x6 — Person 2 has offered the state
0x7 — The channel is closed
The deposit perform receives a message from a easy pockets (switch) with a further physique payload.
Depositing GRAMs to the channel:
- The consumer generates a further physique payload that features a message (for instance, 1 bit) and its signature in a separate .fif file.
- Physique payload is compiled to a .boc file.
- Physique payload is loaded from this .boc file right into a .fif file as a body-cell “transferring” reference (the .fif is liable for transferring GRAMs from the pockets).
- The recv_external perform is known as with arguments (the deposit quantity and the vacation spot tackle of the channel) when the compiled .fif file is distributed to the community.
- The send_raw_message perform is executed. Deposited GRAMs and extra physique payload is distributed to a P2P channel good contract vacation spot tackle.
- The recv_internal perform of the P2P channel good contract is known as. GRAMs are acquired by channel contracts.
The deposit perform might be referred to as if the state of the P2P channel good contract is 0x1 or 0x2 or 0x3.
FunC code that checks the state:
Solely the house owners of the general public keys (written within the preliminary storage) are allowed to make a deposit. The good contract checks the signature of every inner message that will probably be acquired via the recv_internal perform. If the message is signed by one of many public key house owners, the contract standing adjustments to 0x2 or 0x3 (0x2 whether it is public key 1 and 0x3 whether it is public key 2). If all customers have made a deposit, the contract standing adjustments to 0x4 on the identical perform name.
The FunC code liable for altering contract standing:
Funds might be returned if a counterparty has not made a deposit on time.
To do this, a consumer wants to supply their tackle and signature through exterior message. The funds will probably be refunded if the offered signature belongs to public key 1 or public key 2 (individuals who made a deposit) and the contract standing is 0x2 or 0x3.
FunC code that’s liable for verifying the refund utility:
Every particular person ought to present an exit state, the signature of this state, and signature of the physique message.
- Good contract tackle (to exclude the potential of coming into the proper state from the earlier P2P channel with the identical contributors).
- The ultimate steadiness of the primary participant.
- The ultimate steadiness of the second participant.
- State quantity.
The physique message signature is saved in the principle slice, the state is saved in a separate reference, and state signatures are saved as references to a “signatures” reference to keep away from cell overflow.
Examine the physique message signature and decide the participant.
Examine that it’s the flip of the participant or 24 hours have handed because the final entered state. Write the flip of the present participant (0x5 or 0x6) to the contract standing.
An instance of an accurate signature of the physique message for the proprietor of first_user_pubkey:
We then must confirm that the good contract tackle written to the state is the precise contract tackle:
Subsequent, we have to confirm signatures beneath the state:
After that, there are two assertions:
- The deposited quantity from the storage must be equal to the sum of the entire balances of the contributors.
- The brand new entered state quantity should be larger than or equal to the earlier one.
In case of new_state_num > state_num we have to retailer new_state_num with the brand new time_to_send equaling to now() + 86401 (24 hours from the present time), and likewise write the precise contract standing (0x5 if first participant made a name, in any other case 0x6).
In one other case, if new_state_num == state_num we have to put a further two references to the “signatures” reference with addresses of every participant and signatures beneath their addresses.
If the signatures are appropriate, GRAMs are withdrawn from one tackle and put into the proprietor’s tackle.
Every time a profitable name occurs, we have to retailer all storage information even when it doesn’t change.
The idea is that the primary consumer deployed the contract and the contributors agreed on commissions. The settlement on commissions in our case is reaching off-chain.
We’ve not but discovered the way to calculate the entire fee, considering the truth that gamers can write an irrelevant state and report precise states after that. Take into account that we have to pay charges from the P2P channel good contract every time we efficiently name recv_internal or recv_external capabilities.
As talked about earlier, we have to add some quantity of GRAMs to a non-bounceable future good contract tackle as a way to initialize it.
On the final day of the competitors, TON’s builders made a decide to the stdlib.fc library with a brand new perform that enables getting the precise good contract steadiness.
Recommendations for potential options to this downside are welcome!
FunC and Fift permit any developer entry to the low-level world of software program engineering, opening new alternatives and options for blockchain builders who’ve already gotten used to Ethereum or every other good contract platform. It will be important that TON is a sharded blockchain, so implementing good contracts on it is tougher. For instance, Ethereum’s contracts run synchronously and don’t require dealing with conditions resembling ready for a solution from one other contract.
The asynchronous approach of good contract communication is the one choice to make it scalable, and TON has these choices. Our answer ended up being harder to implement than Solidity, however there’s all the time a trade-off. It’s positively potential to construct a sophisticated good contract on TON, and the best way that TON’s staff dealt with it is extremely spectacular. We’re trying ahead to seeing extra libraries and instruments that may assist to deploy and construct FunC contracts.
We completely loved all of the duties and need that we’d had extra time to implement all of them. However, we gained two prizes at TON Contest: first place for greatest synchronous fee channel in addition to third place for greatest asynchronous fee channel.
We’ll share our personal private suggestions partly three.
The views, ideas and opinions expressed listed here are the authors’ alone and don’t essentially replicate or symbolize the views and opinions of Cointelegraph.