Add Wrapped TON (wTON)#746
Conversation
|
👋 krebernisak, thanks for creating this pull request! To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team. Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks! |
There was a problem hiding this comment.
Pull request overview
Adds initial Wrapped TON (wTON) Jetton-style contracts plus supporting Jetton library utilities/types.
Changes:
- Introduces wTON
JettonMinterandJettonWalletcontracts and a short README. - Refactors/extends Jetton shared code (errors, fees management, wallet address derivation) and updates message/storage types.
- Updates the Jetton onramp mock example to import the new jetton-utils module.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| contracts/contracts/wton/README.md | Adds brief documentation for the new wTON module. |
| contracts/contracts/wton/JettonWallet.tolk | Implements the wTON Jetton wallet contract (transfers, burns, bounce handling, getters). |
| contracts/contracts/wton/JettonMinter.tolk | Implements the wTON Jetton minter contract (mint/burn handling, wallet address queries, metadata getter). |
| contracts/contracts/lib/jetton/utils.tolk | Removes the previous Jetton utility module. |
| contracts/contracts/lib/jetton/storage.tolk | Updates Jetton storage types (admin fields optional, metadataUri now string). |
| contracts/contracts/lib/jetton/messages.tolk | Updates Jetton message schemas (several fields now optional; metadata update payload type adjusted). |
| contracts/contracts/lib/jetton/jetton-utils.tolk | Adds new wallet address/state-init derivation helpers. |
| contracts/contracts/lib/jetton/fees-management.tolk | Adds shared fee/gas/storage calculations and “enough gas” checks. |
| contracts/contracts/lib/jetton/errors.tolk | Adds shared Jetton error constants. |
| contracts/contracts/examples/jetton/onramp_mock.tolk | Updates imports and local constants to align with the Jetton refactor. |
Comments suppressed due to low confidence (1)
contracts/contracts/lib/jetton/fees-management.tolk:58
- Spelling typo in comment: "iternal_transfer" should be "internal_transfer".
// but last one is optional (it is ok if it fails)
fwdCount * fwdFee +
forwardInitStateOverhead() + // additional fwd fees related to initstate in iternal_transfer
calculateGasFee(MY_WORKCHAIN, sendTransferGasConsumption) +
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| in.bouncedBody.skipBouncedPrefix(); | ||
|
|
||
| val msg = lazy BounceOpToHandle.fromSlice(in.bouncedBody); |
| fun onBouncedMessage(in: InMessageBounced) { | ||
| in.bouncedBody.skipBouncedPrefix(); | ||
| // process only mint bounces; on other messages, an exception will be thrown, it's okay | ||
| val msg = lazy InternalTransferStep.fromSlice(in.bouncedBody); | ||
|
|
||
| var storage = lazy MinterStorage.load(); | ||
| storage.totalSupply -= msg.jettonAmount; | ||
| storage.save(); |
| @@ -0,0 +1,73 @@ | |||
| // SPDX-License-Identifier: MIT | |||
| // Imported from https://github.com/ton-blockchain/tolk-bench/blob/0f416ca611fbfa25e736973d01e5fb70af485468/contracts_Tolk/03_notcoin/messages.tolk | |||
| } | ||
|
|
||
| fun checkAmountIsEnoughToTransfer(msgValue: int, forwardTonAmount: int, fwdFee: int) { | ||
| var fwdCount = forwardTonAmount != 0 ? 2 : 1; // second sending (forward) will be cheaper that first |
| return { | ||
| workchain: MY_WORKCHAIN, | ||
| stateInit: { | ||
| code: jettonWalletCode, |
There was a problem hiding this comment.
I wonder if there's a way to use the hash of the code instead to save on storage and compute fees. IIUC the hash is computed from leaves to root, so the hash of the code should always result in the same.
| // SPDX-License-Identifier: MIT | ||
|
|
||
| const ERROR_INVALID_OP = 72 | ||
| const ERROR_WRONG_OP = 0xffff |
| const ERROR_WRONG_WORKCHAIN = 333 | ||
| const ERROR_BALANCE_ERROR = 47 | ||
| const ERROR_NOT_ENOUGH_GAS = 48 | ||
| const ERROR_INVALID_MESSAGE = 49 |
| val excessesMsg = createMessage({ | ||
| bounce: BounceMode.NoBounce, | ||
| dest: msg.sendExcessesTo, | ||
| value: 0, |
There was a problem hiding this comment.
But we should be sending that amount of TON, right?
There was a problem hiding this comment.
We're sending whatever bounced after a failed mint with SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE
| bounce: BounceMode.Only256BitsOfBody, | ||
| dest: calcDeployedJettonWallet(msg.mintRecipient, contract.getAddress(), storage.jettonWalletCode), | ||
| value: msg.tonAmount, | ||
| body: msg.internalTransferMsg, |
There was a problem hiding this comment.
Why do we have owner checks here? I think this should be permissionless. We are missing:
- checking that incomming value is greater than msg.tonAmount
- There is redundancy between MintNewJettons.tonAmount and internalTransferMsg.jettonAmount. Maybe we can drop MintNewJettons.tonAmount. Otherwise, we should be asserting both match
- we need to reserve jettonAmount of TON
There was a problem hiding this comment.
Please check the updated code.
There is redundancy between MintNewJettons.tonAmount and internalTransferMsg.jettonAmount. Maybe we can drop MintNewJettons.tonAmount. Otherwise, we should be asserting both match
Not redundant, they are used differently; MintNewJettons.tonAmount is the TON sent with internalTransferMsg and nternalTransferMsg.jettonAmount is the Jetton amount. Now Jetton amount should equal TON amount so we update the sent value with value: jettonAmount + msg.tonAmount,
No description provided.