Support bounced(msg: CustomMessage)
It will be nice if users did not have to parse bounced messages themselves and can instead use Tact to route automatically by type like it does with receivers
// this is func :D
bounced(msg: Slice) {
msg.skipBits(32); // 0xFFFFFFFF
let op: Int = msg.loadUint(32);
let queryId: Int = msg.loadUint(64);
let jettonAmount: Int = msg.loadCoins();
It is not possible since bounced message only has 256 bits of the sent message, not the whole one.
Let's think together before you shut it down :)
Handling bounced messages is not an advanced use-case, we should attempt to make it straightforward.
Developers that aren't used to async contracts will have a hard time dealing with rollbacks on errors. We should go out of our way not to make this even more complicated by making them parse the messages manually. I'm not sure even where they can find the op value of auto generated Messages.
Here's an idea:
What if we support bounced message routing, but only for small messages whose total size is guaranteed to always be below 256 bit. I think that in real life, this should satisfy 90% of the cases.
If the user would try to route bounced(msg: CustomMessage) for a potentially larger message, the compiler will give a compilation error.
No, this is a false assumption. For example jettons put amount in the beginning of the message to be able to revert. Jetton messages could be quite big and contain much more information than needed for revert.
I know, if the message is potentially larger than 256 bit and the user wants to handle its bounce, they will have to parse it manually from a slice. Like in jetton. But I believe this is an edge case.
Let's say I send this message from my contract and it may bounce:
message Increment {
amount: Int as uint32;
}
The size of this message is 4+32 (without queryid) or 4+32+64 with queryid, in any case it's under 256 bit.
So just for this specific message I should be able to write the following:
bounced(msg: Increment) {
}
And the compiler will allow me to do that. Obviously if the message is potentially larger, the compiler will not allow me to do that (like in jetton case) and give a compilation error. Then I will have no choice except manual parsing of beginning of message from a slice like in jettons.
I think it's ok, because if a developer needs to handle rollbacks in their code, they will have incentive to keep the messages small so the code becomes simpler.
If we would have a legitimate example where it could work, I will add this. Right now there are no real examples. All contracts I have written are not able to fit everything to (256-32) = 224 bits
ok fair. new idea :)
what if we always support bounced routing, even if the message is potentially larger than 256 bit.
and the compiler will throw a compilation error if the user tries to access any field of the message beyond the 256 bit mark.
so jettons is actually possible with simpler syntax:
bounced(msg: TokenTransferInternal) {
// Update balance
self.balance = self.balance + msg.amount;
}
This code will compile because the field msg.amount is before the 256 bit mark
and what about fields with dynamic length? like coins or addresses
This was implemented in 1.1.0