From 89a9e2c2f6941ee07d9a57e92d9eef4cda1aa7d2 Mon Sep 17 00:00:00 2001
From: ya7on <hello@syoma.website>
Date: Sun, 29 Sep 2024 12:53:51 +0300
Subject: [PATCH] feat: add jetton burn

---
 contracts/teps/tep74.tact  |  15 ++++++
 tests/JettonWallet.spec.ts | 107 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/contracts/teps/tep74.tact b/contracts/teps/tep74.tact
index 7adbc9e..f750b53 100644
--- a/contracts/teps/tep74.tact
+++ b/contracts/teps/tep74.tact
@@ -31,6 +31,21 @@ trait TEP74JettonMaster with TEP64Metadata {
     // Jetton symbol field in metadata
     jetton_symbol: String;
 
+    receive(msg: JettonBurnInternal){
+        let ctx = context();
+        let init = self.generate_wallet_state_init(msg.sender);
+        let wallet_address = contractAddress(init);
+        nativeThrowUnless(ERROR_CODE_INVALID_OWNER, ctx.sender == wallet_address);
+        send(SendParameters{
+                to: msg.response_destination,
+                value: 0,
+                mode: SendRemainingValue | SendIgnoreErrors,
+                bounce: false,
+                body: msg.toCell()
+            }
+        );
+    }
+
     get fun get_jetton_data(): JettonMasterData {
         let jetton_content = self.jetton_master_metadata(self.jetton_name, self.jetton_description, self.jetton_symbol);
         return
diff --git a/tests/JettonWallet.spec.ts b/tests/JettonWallet.spec.ts
index 77e4705..3a735fb 100644
--- a/tests/JettonWallet.spec.ts
+++ b/tests/JettonWallet.spec.ts
@@ -68,7 +68,7 @@ describe('JettonMaster', () => {
                 destination: other.address,
                 custom_payload: null,
                 forward_payload: new Builder().asSlice(),
-                forward_ton_amount: 0n,
+                forward_ton_amount: 1n,
                 response_destination: other.address,
             }
         );
@@ -86,6 +86,17 @@ describe('JettonMaster', () => {
             success: true,
             op: 0x178d4519,
         });
+        expect(transferResult.transactions).toHaveTransaction({
+            from: otherJettonWallet.address,
+            to: other.address,
+            op: 0x7362d09c,
+        });
+        expect(transferResult.transactions).toHaveTransaction({
+            from: otherJettonWallet.address,
+            to: other.address,
+            success: true,
+            op: 0xd53276db,
+        });
 
         let jettonWalletData = await jettonWallet.getGetWalletData();
         expect(jettonWalletData.balance).toEqual(toNano("1337") - toNano("228"));
@@ -153,4 +164,98 @@ describe('JettonMaster', () => {
         let jettonWalletData = await jettonWallet.getGetWalletData();
         expect(jettonWalletData.balance).toEqual(toNano("1337"));
     });
+
+    it('should burn tokens', async () => {
+        const transferResult = await jettonWallet.send(
+            deployer.getSender(),
+            {
+                value: toNano("0.05"),
+            },
+            {
+                $$type: 'JettonBurn',
+                query_id: 0n,
+                amount: toNano("1337"),
+                response_destination: deployer.address,
+                custom_payload: null,
+            }
+        );
+        expect(transferResult.transactions).toHaveTransaction({
+            from: deployer.address,
+            to: jettonWallet.address,
+            deploy: false,
+            success: true,
+            op: 0x595f07bc,
+        });
+        expect(transferResult.transactions).toHaveTransaction({
+            from: jettonWallet.address,
+            to: jettonMaster.address,
+            deploy: false,
+            success: true,
+            op: 0x7bdd97de,
+        });
+        expect(transferResult.transactions).toHaveTransaction({
+            from: jettonMaster.address,
+            to: deployer.address,
+            deploy: false,
+            success: true,
+            op: 0x7bdd97de,
+        });
+
+        let jettonWalletData = await jettonWallet.getGetWalletData();
+        expect(jettonWalletData.balance).toEqual(toNano("0"));
+    });
+
+    it('should not burn tokens not owner', async () => {
+        const transferResult = await jettonWallet.send(
+            other.getSender(),
+            {
+                value: toNano("0.05"),
+            },
+            {
+                $$type: 'JettonBurn',
+                query_id: 0n,
+                amount: toNano("228"),
+                response_destination: deployer.address,
+                custom_payload: null,
+            }
+        );
+        expect(transferResult.transactions).toHaveTransaction({
+            from: other.address,
+            to: jettonWallet.address,
+            deploy: false,
+            success: false,
+            op: 0x595f07bc,
+            exitCode: 132,
+        });
+
+        let jettonWalletData = await jettonWallet.getGetWalletData();
+        expect(jettonWalletData.balance).toEqual(toNano("1337"));
+    });
+
+    it('should not burn tokens not enough amount', async () => {
+        const transferResult = await jettonWallet.send(
+            deployer.getSender(),
+            {
+                value: toNano("0.05"),
+            },
+            {
+                $$type: 'JettonBurn',
+                query_id: 0n,
+                amount: toNano("100500"),
+                response_destination: deployer.address,
+                custom_payload: null,
+            }
+        );
+        expect(transferResult.transactions).toHaveTransaction({
+            from: deployer.address,
+            to: jettonWallet.address,
+            deploy: false,
+            success: false,
+            op: 0x595f07bc,
+            exitCode: 6901,
+        });
+
+        let jettonWalletData = await jettonWallet.getGetWalletData();
+        expect(jettonWalletData.balance).toEqual(toNano("1337"));
+    });
 });