You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.3 KiB

import "@stdlib/ownable";
import "./wallet";
import "./linker";
2 years ago
import "./constants";
2 years ago
import "./staking";
@interface("org.ton.jetton.master")
2 years ago
trait TONBTrait with Ownable, StakingTrait {
//
// Storage
//
totalSupply: Int;
mintable: Bool;
owner: Address;
content: Cell?;
first_linker: Address?;
last_linker: Address?;
n_linkers: Int = 0;
2 years ago
staking_pool: Address?;
in_the_pool: Int = 0;
2 years ago
withdrawal_requests: WithdrawalRequests;
requested_withdrawal: Int = 0;
//
// 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;
2 years ago
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,
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);
2 years ago
return;
}
// Withdraw
send(SendParameters{
to: msg.owner,
value: msg.amount - withdraw_gas_consumption,
bounce: false
});
}
2 years ago
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);
2 years ago
let linker_init: StateInit = initOf Linker(self.n_linkers, walletAddress, myAddress());
let linker_address: Address = contractAddress(linker_init);
send(SendParameters{
2 years ago
to: linker_address,
value: linker_credit,
bounce: false,
2 years ago
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,
2 years ago
forwardPayload: emptySlice(),
setLinker: self.n_linkers - 1,
setLinkerAddress: linker_address
2 years ago
}.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);
}
}