import "@stdlib/ownable"; import "./wallet"; import "./linker"; import "./constants"; import "./staking"; @interface("org.ton.jetton.master") trait TONBTrait with Ownable, StakingTrait { // // Storage // totalSupply: Int; mintable: Bool; owner: Address; content: Cell?; first_linker: Address?; last_linker: Address?; n_linkers: Int = 0; staking_pool: Address?; in_the_pool: Int = 0; withdrawal_requests: WithdrawalRequests; // // Receivers // receive(msg: TokenUpdateContent) { // Allow changing content only by owner self.requireOwner(); // Update content self.content = msg.content; } receive(msg: TokenBurnNotification) { // Check wallet self.requireWallet(msg.owner); // Update supply self.totalSupply = self.totalSupply - msg.amount; let available: Int = myBalance() - tonb_floor - withdraw_gas_consumption; if (available < msg.amount) { /* if not enough tokens, withdraw what we have, send some tokens to the owner, add a withdrawal request (-withdrawal_gas) */ let diff: Int = msg.amount - available; send(SendParameters{ to: msg.owner, value: myBalance() - tonb_floor - withdraw_gas_consumption, bounce: false }); let body: Cell = TokenTransferInternal{ amount: diff, queryId: 0, from: myAddress(), responseAddress: myAddress(), forwardTonAmount: 0, forwardPayload: emptySlice(), setLinker: null, setLinkerAddress: null }.toCell(); let walletAddress: Address = self.get_wallet_address(msg.owner); send(SendParameters{ to: walletAddress, value: 0, bounce: false, mode: SendRemainingValue, body: body }); let ctx: Context = context(); self.requestWithdrawal(ctx.sender, diff); return; } // Withdraw send(SendParameters{ to: msg.owner, value: msg.amount - withdraw_gas_consumption, bounce: false }); } receive(msg: BlacklistWallet) { // Allow blacklisting only by owner self.requireOwner(); // Blacklist wallet let winit: StateInit = self.getJettonWalletInit(msg.wallet); let walletAddress: Address = contractAddress(winit); send(SendParameters{ to: walletAddress, value: 0, mode: SendRemainingValue, bounce: false, body: msg.toCell() }); } // // Get Methods // get fun get_wallet_address(owner: Address): Address { let winit: StateInit = self.getJettonWalletInit(owner); return contractAddress(winit); } get fun get_jetton_data(): JettonData { let code: Cell = self.getJettonWalletInit(myAddress()).code; return JettonData{ totalSupply: self.totalSupply, mintable: self.mintable, owner: self.owner, content: self.content, walletCode: code }; } // // Private Methods // fun mint(to: Address, amount: Int, responseAddress: Address?) { // Update total supply self.totalSupply = self.totalSupply + amount; // Create message let winit: StateInit = self.getJettonWalletInit(to); let walletAddress: Address = contractAddress(winit); let linker_init: StateInit = initOf Linker(self.n_linkers, walletAddress, myAddress()); let linker_address: Address = contractAddress(linker_init); send(SendParameters{ to: linker_address, value: linker_credit, bounce: false, body: SetLinkerNeighbor{ neighbor: self.last_linker }.toCell(), code: linker_init.code, data: linker_init.data }); self.last_linker = linker_address; self.n_linkers = self.n_linkers + 1; let wallet_msg_body: Cell = TokenTransferInternal{ amount: amount, queryId: 0, from: myAddress(), responseAddress: responseAddress, forwardTonAmount: 0, forwardPayload: emptySlice(), setLinker: self.n_linkers - 1, setLinkerAddress: linker_address }.toCell(); send(SendParameters{ to: walletAddress, value: wallet_credit, bounce: false, body: wallet_msg_body, code: winit.code, data: winit.data }); } receive(msg: RequestLinker) { let ctx: Context = context(); let winit: StateInit = self.getJettonWalletInit(msg.client); let walletAddress: Address = contractAddress(winit); require(walletAddress == ctx.sender, "invalid sender"); let linker_init: StateInit = initOf Linker(self.n_linkers, walletAddress, myAddress()); let linker_address: Address = contractAddress(linker_init); send(SendParameters{ to: linker_address, value: linker_credit, bounce: false, body: SetLinkerNeighbor{ neighbor: self.last_linker }.toCell(), code: linker_init.code, data: linker_init.data }); self.last_linker = linker_address; self.n_linkers = self.n_linkers + 1; let wallet_msg_body: Cell = TokenTransferInternal{ amount: 0, queryId: 0, from: myAddress(), responseAddress: myAddress(), forwardTonAmount: 0, forwardPayload: emptySlice(), setLinker: self.n_linkers - 1, setLinkerAddress: linker_address }.toCell(); send(SendParameters{ to: walletAddress, value: wallet_credit, bounce: false, body: wallet_msg_body, code: winit.code, data: winit.data }); } fun burn(from: Address, amount: Int, responseAddress: Address?) { // Create message let winit: StateInit = self.getJettonWalletInit(from); let walletAddress: Address = contractAddress(winit); send(SendParameters{ to: walletAddress, value: 0, bounce: false, mode: SendRemainingValue, body: TokenBurn{ amount: amount, queryId: 0, responseAddress: responseAddress, owner: from }.toCell(), code: winit.code, data: winit.data }); } fun requireWallet(owner: Address) { let ctx: Context = context(); let winit: StateInit = self.getJettonWalletInit(owner); require(contractAddress(winit) == ctx.sender, "Invalid sender"); } virtual fun getJettonWalletInit(address: Address): StateInit { return initOf TONBWallet(myAddress(), address); } }