TEP-137: Jetton Wallet Balance Query
It will never be accepted.
For example in situations where the smart contract knows that no outbound transfer can happen between the
get_balancecall and theget_balance_responsereply (for example when a smart contract queries its own balance), the smart contract can know the minimum amount of Jetton tokens it holds.
In this case contract should block processing all over messages which can change balance until it receives get_balance_response. In can require up to few minutes. Very easy to make mistake for developers without big experience in async networks.
In this case contract should block processing all over messages which can change balance until it receives get_balance_response. In can require up to few minutes.
This is simply not true. In my example where the contract just wants to make sure its balance is greater than x, as long as the contract doesn't transfer funds out (i.e. the balance doesn't reduce) it can keep processing other messages, and if it receives a response that is at least x it can proceed.
Very easy to make mistake for developers without big experience in async networks.
As I have stated multiple times in the document, it should up to the dapp developer to correctly use this feature. You can't cripple experienced async developers for the reason that the feature can "potentially be misused by inexperienced developers". We can mitigate the misuse risk by providing clear explanations in the documentation (which I have already done in the standard).
Bumping this since we've again run into issues related to this design flaw.
Saying "you can't query the balance since the balance might change" is equivalent to your bank or credit card company refusing to give you an account statement because "someone might have charged your card in the meantime".
I feel this should be accompanied with a good programming language with marker structs which would allow to track assumptions.
struct ValidOnce;
struct ValidThisTx;
struct ValidForever;
trait ValidityTicket {}
impl ValidityTicket for ValidOnce {}
impl ValidityTicket for ValidThisTx {}
impl ValidityTicket for ValidForever {}
async fn send_jettons_or_refund(jettons: usize) {
let my_jetton_wallet = todo!();
let my_balance: (usize, ValidOnce) = my_jetton_wallet.request_balance().await; // <-- TRANSACTION BOUNDARY
// SAFETY: all jetton send requests are routed through balance request
// thus they are processed in order (by lt), and our balance is at least what we received
let my_balance: (usize, ValidThisTx) = unsafe {my_balance.fiat_extend()};
(if my_balance.0 < jettons {
send_refund()
} else {
my_jetton_wallet.transfer(todo!(), jettons, my_balance)
}).await; // <-- TRANSACTION BOUNDARY
}
let my_balance: (usize, ValidOnce) = my_jetton_wallet.request_balance().await; // <-- TRANSACTION BOUNDARY
this expression is not feasible on TON since call context is not preserved.
If destination contract can be trusted to return a cell as-is, then continuation with needed temporary variables may be passed. If there are few overlapping "calls" on each moment of time, then continuation may be stored in a dictionary.