TEPs icon indicating copy to clipboard operation
TEPs copied to clipboard

TEP: Wrapped TON standard and implementation

Open markokhman opened this issue 2 years ago • 13 comments

Publishing this as a draft. The work is in process and will be lot's of updates in upcoming days. Please leave your comments.

markokhman avatar Nov 29 '22 21:11 markokhman

Hello guys, could you please review this one?

markokhman avatar Dec 19 '22 10:12 markokhman

LGTM

Naltox avatar Dec 22 '22 15:12 Naltox

Hello colleagues!

At ston.fi we offer to update WTON standard to actually transfers TON between wallets when transferring WTON. This approach avoid custom minting calls and works without the need of custom code in any protocol to support it.

Concepts

Unlike current WTON implementations, we propose to not rely on wrapping/unwrapping logic. In this standard, minting WTON doesn’t touch central jetton contract, minting occurs when the user sends TON to a his WTON wallet. The amount of gas transferred betwen WTON Jetton Wallets is actually the amount of TON sent + some gas for wallet processing. In this way, each wallet will actually store native TON in each wallet without the need of a central autorithy. The jetton transfer amount should be paid from both wallet balance and incoming message gas, prioritizing the WTON wallet balance. Eg: I want to transfer 10 WTON, my message carry 3 TON and my WTON wallet has 8 TON in it, after the transfer the amount of gas left should be 1 WTON and WTON Wallet Balance 0. To "withdraw" TON from your own WTON wallet, you call either call a standard burn or can be enabled by default in internal jetton wallet configuration. In this way, you can specify a condition to trigger an auto-withdraw function described in the following document. The outgoing withdraw message should be paid from WTON Wallet TON balance.

Specification

The following opcodes describes only the non-standard core logic needed in the implementation.

// minter
// deploy_wallet: deploy a new wallet contract for a specified to_address address. Can be called by anyone.
// required because there is no central minting. Outgoing message should have an empty body
deploy_wallet#0x656ff420 query_id:uint64 destination:MsgAddress = InternalMsgBody;

// wallet 
// change_mode: changes jettonwallet behavior
// mode=0 means no autounwrap, mode=1 means autounwrap if condition is met (balance > min_balance)
change_mode#0x3508d282 query_id:uint64 mode:Bool min_balance:(VarUInteger 16) = InternalMsgBody;

Pros:

  • Lower gas consumption for WTON transfers with auto wrap/unwrap
  • Simplier message construction

Cons:

  • Impossible to determine total_supply in WTON minter

dariotarantini avatar Jan 11 '23 14:01 dariotarantini

I want to emphasize some aspects of @dariotarantini proposal:

  1. each wTON wallet works as minter/burner itself - no need for additional interaction with minter which means one or even two transaction shorter paths
  2. we can reformulate this scheme in the following terms: in original proposal when we want to send TONs we actually send IOU jettons which is redeemable as TON, but in scheme proposed by Dario we send TON themselves but disguised as jetton transfer for compatibility.

It is important to stress that we should be quite cautious about fee-managing to make these wTON fully Jetton compatible. I propose to ensure that amount of TON sent with each inter-wallet transfer to be equal to amount of TON which would be sent in the case it is standard jetton + amount of jettons in message. Anyway, wTON-wallet of the receiver should not trust amount of jetton in incoming internal transfer, instead it should calculate amount that was really sent (TON amount minus all forward amounts/fees).

Another important point is way to unwrap. Dario propose to make auto-unwrap option on jetton wallet, while there is also an option that wallet will peek in payload and if there something very special (that will not intersects with standard transfer) it will understand that it should not send TON as jettons to the other wTON wallet, but unwrap it directly to destination. I used 23bit long prime number as that special payload (since it is expected that for any usual purpose there will be 32bit long op) My very draft (not tested at all !!!) implementation is https://github.com/EmelyanenkoK/wTON

EmelyanenkoK avatar Jan 11 '23 14:01 EmelyanenkoK

while there is also an option that wallet will peek in payload and if there something very special (that will not intersects with standard transfer) it will understand that it should not send TON as jettons to the other wTON wallet, but unwrap it directly to destination.

This assume that, if you are interacting with another contract, the receiver contract will forward the payload in the next transaction. Some may not; that's why I proposed an alternative on user-side, similar to status in stablecoin contract.

dariotarantini avatar Jan 11 '23 14:01 dariotarantini

This assume that, if you are interacting with another contract, the receiver contract will forward the payload in the next transaction. Some may not; that's why I proposed an alternative on user-side, similar to status in stablecoin contract.

Not forcing my option, just emphasize that my implementation differs from your suggestion. By the way, why not have both?

Also in my implementation reading of special op and thus "unwrapping" happens on the receiver jetton-wallet. Now I understand that it is excessive: sender wallet may peek into payload as well and unwrap and send TONs to destination itself (minus yet another tx in chain).

EmelyanenkoK avatar Jan 11 '23 15:01 EmelyanenkoK

Hey @dariotarantini @EmelyanenkoK, thank you very much for this suggestion! Very interesting idea with shifting the mint/burn logic into the WTON wallet, eliminating centralised minter. I will have a deeper look and play around with your implementation draft @EmelyanenkoK

Thank you very much!

markokhman avatar Jan 11 '23 15:01 markokhman

By the way, why not have both?

Correct me if I'm wrong, but in your proposal the receiver has no way to refuse an auto-unwrap payment, right? In the case of the receiver is a DEX, the sender may set the special op and the DEX contract will receive native TON. But the DEX has no way to handle correctly this, leading to inconsistency where the payment has been done, but the DEX is not supposed to manually send a fixed amount of TON.

dariotarantini avatar Jan 11 '23 15:01 dariotarantini

@markokhman I just want to say that I'm not going to polish my implementation till release quality. It was done to check the idea, I hope that if you embrace the whole concept, team behind this TEP will make final implementation (whether based on mine or from scratch).

@dariotarantini I have the following idea in my head: by default wTON will not be unwrapped. Sender may force "unwrap" by putting magic number into payload of transfer request to his own wallet. In this case TONs will be unwrapped on sender wallet and sent directly to the destination (instead of sending wTONs to destination wallet). If Sender doesn't enforce unwrap, wTON will came to destination wallet. This wallet can have mode as you suggested and unwrap (or not) all incoming wTONs as owner desires.

That way, I believe we get benefits from both approaches and no downsides. Indeed ability sender to forcefully unwrap wTONs does not make system more unpredictable: sender always have privilege to shot his leg (and for instance send TON directly instead of through wTON system). But this combined scheme allows both sender auto-unwrap tokens and receiver auto-unwrap token if wanted.

EmelyanenkoK avatar Jan 11 '23 17:01 EmelyanenkoK

@EmelyanenkoK I understand, sure

We'll first make sure every interested party took their time to view and comment, the will do further code polishing on our end if needed.

Thank you very much!

markokhman avatar Jan 11 '23 18:01 markokhman

@dariotarantini @EmelyanenkoK I have read in detail both an idea description and a draft solution. I've found it much more elegant and effient comparing to a previous implementation. Also I like the idea of having a "magic flag" for auto-unwrapping. I've double-checks all use-cases of DEX and it covers all of them. What are the next steps?

NickNekilov avatar Jan 18 '23 06:01 NickNekilov

@NickNekilov as @EmelyanenkoK have mentioned, we should make sure the solution is ready for production, meaning writing tests and ensuring there is no drawbacks.

I believe it would be great to have some tests that are actually demonstrating core usecases and maybe also those DEX, if that's the case

markokhman avatar Jan 18 '23 06:01 markokhman

I guess next step is explicit listing of additional functionality such as

  • external transfer (it is when you send TON directly to wton-wallet of receiver to wrap it in-place without additional tx)
  • details of auto-unwrap
  • exact mechanics of the the fees with examples: interaction of amount, forward_ton_amount and gas-consumption/min-storage fees

Get consensus from interested parties and then reference implementation.

EmelyanenkoK avatar Jan 18 '23 06:01 EmelyanenkoK