TEPs icon indicating copy to clipboard operation
TEPs copied to clipboard

TEP-137: Jetton Wallet Balance Query

Open 0kenx opened this issue 2 years ago • 8 comments

0kenx avatar Jan 09 '24 22:01 0kenx

It will never be accepted.

For example in situations where the smart contract knows that no outbound transfer can happen between the get_balance call and the get_balance_response reply (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.

mr-tron avatar Jan 18 '24 20:01 mr-tron

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).

0kenx avatar Jan 26 '24 08:01 0kenx

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".

0kenx avatar May 31 '24 12:05 0kenx

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
}

ProgramCrafter avatar Jun 16 '24 07:06 ProgramCrafter

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.

0kenx avatar Jun 17 '24 10:06 0kenx

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.

ProgramCrafter avatar Jun 17 '24 11:06 ProgramCrafter