Skip to content

Commit

Permalink
Merge pull request #4 from Ton-Dynasty/mainnet
Browse files Browse the repository at this point in the history
Mainnet
  • Loading branch information
alan890104 authored May 1, 2024
2 parents 3ff6f55 + 99cd280 commit 8b55db9
Show file tree
Hide file tree
Showing 26 changed files with 968 additions and 126 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ temp
build
dist
.DS_Store
.env
.env
*.txt
5 changes: 0 additions & 5 deletions JettonMasterChefCosts.txt

This file was deleted.

5 changes: 0 additions & 5 deletions TONMasterChefCosts.txt

This file was deleted.

Binary file not shown.
51 changes: 40 additions & 11 deletions contracts/jetton_master_chef.tact
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ contract JettonMasterChef with Deployable, MasterChef {
owner: Address;
pools: map<Address, PoolInfo>;
totalAllocPoint: Int as uint256 = 0;
createdAt: Int as uint64 = 0;
deadline: Int as uint64 = 0;
startTime: Int as uint64 = 0;
metaData: Cell;
totalLpSupply: Int = 0; // Caculated total LP supply(In each pool)
reduntantReward: Int = 0; // The redundant reward for the owner
lastWithdrawTime: Int = 0; // The last withdraw time

// For Reward Jetton
mcRewardJettonWallet: Address;
Expand All @@ -33,6 +35,7 @@ contract JettonMasterChef with Deployable, MasterChef {
emit(DeployMasterChef{owner: _owner, seed: _seed}.toCell());
}


// Kitchen contract will send this message to deploy the MasterChef
receive(msg: SetUpJettonMC) {
require(!self.isInitialized, "contract already initialized");
Expand Down Expand Up @@ -82,15 +85,21 @@ contract JettonMasterChef with Deployable, MasterChef {

return;
}

// check if pool exists or exceed the deadline
if(self.pools.get(ctx.sender) == null || now() > self.deadline || now() < self.startTime){
if(self.pools.get(ctx.sender) == null || now() > self.deadline || now() < self.startTime || ctx.value < ton("0.065")){
// Send the jetton back to the sender if pool does not exist
self.sendJetton(ctx.sender, 0, msg.amount, msg.sender, msg.sender, SendRemainingValue);
return;
}

// Send the redundant jetton back to the owner
if(self.totalLpSupply == 0) {
self.reduntantReward = self.reduntantReward + (now() - self.lastWithdrawTime) * self.rewardPerSecond;
}

// Deposit the LP tokens for the user
self.userDeposit(msg, ctx);

}

// MiniChef will send this message to ask MasterChef to send reward
Expand All @@ -101,18 +110,38 @@ contract JettonMasterChef with Deployable, MasterChef {

// MiniChef send this message to ask MasterChef to withdraw LP tokens and harvest reward
receive(msg: WithdrawAndHarvestReply) {
let initCode: StateInit = self._calculateMiniChefInit(msg.sender);
let expectedSender: Address = contractAddress(initCode);
require(expectedSender == sender(), "unexpected sender");
self.requireMiniChef(msg.sender);

let ctx: Context = context();
if (msg.rewardAmount > 0) {
// Send Reward to the beneficiary
self.sendJetton(self.mcRewardJettonWallet, ctx.value / 2, msg.rewardAmount, msg.beneficiary, msg.beneficiary, 0);
}

// Send Reward to the beneficiary
self.sendJetton(self.mcRewardJettonWallet, ctx.value / 2, msg.rewardAmount, msg.beneficiary, msg.beneficiary, 0);
if(msg.withdrawAmount > 0) {
// Withdraw lpToken to msg.beneficiary
let pool: PoolInfo = self.pools.get(msg.lpTokenAddress)!!;
pool.lpSupply = pool.lpSupply - msg.withdrawAmount;
self.totalLpSupply = self.totalLpSupply - msg.withdrawAmount;
self.lastWithdrawTime = now();
self.pools.set(ctx.sender, pool);
self.sendJetton(pool.lpTokenAddress, ctx.value / 2, msg.withdrawAmount, msg.beneficiary, msg.beneficiary, 0);

// Withdraw lpToken to msg.beneficiary
let pool: PoolInfo = self.pools.get(msg.lpTokenAddress)!!;
self.sendJetton(pool.lpTokenAddress, ctx.value / 2, msg.withdrawAmount, msg.beneficiary, msg.beneficiary, 0);
}
}

receive("Redeem") {
let ctx: Context = context();
require(ctx.value > ton("0.05"), "Not enough TON to redeem");
if(self.totalLpSupply == 0) {
let time: Int = min(now(), self.deadline);
self.reduntantReward = self.reduntantReward + (time - self.lastWithdrawTime) * self.rewardPerSecond;
self.lastWithdrawTime = now();
}
if(self.reduntantReward > 0) {
self.sendJetton(self.mcRewardJettonWallet, 0, self.reduntantReward, self.owner, self.owner, SendRemainingValue);
self.reduntantReward = 0;
}
}

// Get Methods //
Expand Down
7 changes: 4 additions & 3 deletions contracts/kitchen.tact
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ contract Kitchen with Deployable {
body: SetUpJettonMC{
owner: msg.owner,
thunderMintWallet: self.owner,
thunderMintJettonWallet: msg.thunderMintJettonWallet,
mcRewardJettonWallet: msg.mcRewardJettonWallet,
metaData: msg.metaData,
totalReward: msg.totalReward,
deadline: msg.deadline,
startTime: msg.startTime
startTime: msg.startTime,
queryId: msg.queryId
}.toCell(),
code: initCode.code,
data: initCode.data
Expand All @@ -48,7 +48,8 @@ contract Kitchen with Deployable {
metaData: msg.metaData,
totalReward: msg.totalReward,
deadline: msg.deadline,
startTime: msg.startTime
startTime: msg.startTime,
queryId: msg.queryId
}.toCell(),
code: initCode.code,
data: initCode.data
Expand Down
25 changes: 18 additions & 7 deletions contracts/messages.tact
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ message(0x7362d09c) JettonTransferNotification {
message(0x89265822) BuildJettonMasterChef {
owner: Address; // Owner of the MasterChef
seed: Int as uint256; // Seed for the MasterChef
thunderMintJettonWallet: Address; // ThunderMint Wallet address to collect the fee in Jetton
mcRewardJettonWallet: Address; // MasterChef Wallet address for reward jetton
metaData: Slice; // MetaData for the MasterChef, such as name, image url and description
totalReward: Int as coins; // Total reward for the MasterChef
deadline: Int as uint64; // MasterChef distribution deadline
startTime: Int as uint64; // Start Mining Time
queryId: Int as uint64; // arbitrary request number
}

// For MasterChef Contract
Expand All @@ -38,15 +38,16 @@ message(0xf6cf7e6c) SetUpJettonMC {
owner: Address; // Owner (deployer) of the MasterChef
mcRewardJettonWallet: Address; // MasterChef Wallet address for reward jetton
thunderMintWallet: Address; // ThunderMint Wallet address to collect the fee in TON
thunderMintJettonWallet: Address; // ThunderMint Wallet address to collect the fee in Jetton
metaData: Slice; // MetaData for the MasterChef
totalReward: Int as coins; // Total reward for the MasterChef
deadline: Int as uint64; // MasterChef distribution deadline
startTime: Int as uint64; // Start Mining Time
queryId: Int as uint64; // arbitrary request number
}
message(0x4b7d1ae4) AddPool{
lpTokenAddress: Address; // Pool Factory LP token Wallet address
allocPoint: Int as uint256; // How many allocation points assigned to this pool.
queryId: Int as uint64; // arbitrary request number
}

message(0x5e653b7f) UpdatePool {
Expand Down Expand Up @@ -139,6 +140,7 @@ message(0x8bf38613) SetUpTonMC {
totalReward: Int as coins; // Total reward for the MasterChef
deadline: Int as uint64; // MasterChef distribution deadline
startTime: Int as uint64; // Start Mining Time
queryId: Int as uint64; // arbitrary request number
}

message(0xd449b642) BuildTonMasterChef {
Expand All @@ -148,6 +150,7 @@ message(0xd449b642) BuildTonMasterChef {
totalReward: Int as coins; // Total reward for the MasterChef
deadline: Int as uint64; // MasterChef distribution deadline
startTime: Int as uint64; // Start Mining Time
queryId: Int as uint64; // arbitrary request number
}

// Event: Deploy MasterChef
Expand Down Expand Up @@ -190,16 +193,24 @@ struct MasterChefData {
totalReward: Int as coins; // Total reward
}

struct RedeemData {
reduntantReward: Int as coins; // Redundant reward,
totalLpSupply: Int as coins;
lastWithdrawTime: Int;
}

// Constants
const THUNDER_FEE: Int = ton("0.01"); // User have to pay the fee to ThunderMint
const ACC_PRECISION: Int = pow(10, 12); // Precision for the accumulated reward per share
const THUNDER_FEE: Int = ton("0.01"); // User have to pay the fee to ThunderMint
const ACC_PRECISION: Int = pow(10, 20); // Precision for the accumulated reward per share
const ZERO_ADDRESS: Address = address("0QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkT");
const FEE_PERCENT_FOR_DEV: Int = 3; // 0.3% of the reward will be given to the ThunderMint
const MIN_GAS_FEE: Int = ton("0.05"); // Minimum gas fee for calling send ton
const FEE_PERCENT_FOR_DEV: Int = 3; // 0.3% of the reward will be given to the ThunderMint
const MIN_GAS_FEE: Int = ton("0.05"); // Minimum gas fee for calling send ton
const gasConsumption: Int = ton("0.0059");

// ERROR CODES
const ERROR_POOL_NOT_FOUND: Int = 1002;
const ERROR_WRONG_AUTH: Int = 1004;
const ERROR_NO_REWARD: Int = 1005;
const ERROR_NOT_INITIALIZED: Int = 1006;
const ERROR_NOT_INITIALIZED: Int = 1006;
const ERROR_DEADLINE_LT_STARTTIME: Int = 29462;
const ERROR_DEADLINE_STARTTIME_ZERO: Int = 62197;
47 changes: 37 additions & 10 deletions contracts/mini_chef.tact
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ contract MiniChef with Deployable {
userInfo.amount = userInfo.amount + msg.amount;
userInfo.rewardDebt = userInfo.rewardDebt + msg.rewardDebt;
self.userInfo.set(msg.lpTokenAddress, userInfo);
let ctx: Context = context();
let sendBackTon: Int = ctx.value - gasConsumption - MIN_GAS_FEE;
// Send remain Ton to owner
send(SendParameters{
to: self.owner,
value: 0,
mode: SendRemainingValue,
value: sendBackTon,
mode: 0,
body: "Deposit Successfully".asComment()
});
}
Expand All @@ -47,11 +49,12 @@ contract MiniChef with Deployable {
userInfo.rewardDebt = userInfo.rewardDebt - msg.rewardDebt;

self.userInfo.set(msg.lpTokenAddress, userInfo);

let ctx: Context = context();
let sendBackTon: Int = ctx.value - gasConsumption;
send(SendParameters{
to: self.masterChef,
value: 0,
mode: SendRemainingValue,
value: sendBackTon,
mode: 0,
body: WithdrawInternalReply{
queryId: msg.queryId,
lpTokenAddress: msg.lpTokenAddress,
Expand All @@ -73,11 +76,13 @@ contract MiniChef with Deployable {
}
userInfo.rewardDebt = accumulatedReward;
self.userInfo.set(msg.lpTokenAddress, userInfo);
let ctx: Context = context();
let sendBackTon: Int = ctx.value - gasConsumption;
// Send pending reward ammount to MasterChef, and then MasterChef will send it to the user
send(SendParameters{
to: self.masterChef,
value: 0,
mode: SendRemainingValue,
value: sendBackTon,
mode: 0,
body: HarvestInternalReply{
queryId: msg.queryId,
lpTokenAddress: msg.lpTokenAddress,
Expand All @@ -93,10 +98,32 @@ contract MiniChef with Deployable {
receive(msg: WithdrawAndHarvestInternal) {
require(sender() == self.masterChef, "only masterChef can harvest");
let userInfo: UserInfo = self.userInfo.get(msg.lpTokenAddress)!!;
require(userInfo.amount >= msg.withdrawAmount, "insufficient balance");
let accumulatedReward: Int = userInfo.amount * msg.accRewardPerShare / ACC_PRECISION;
let _pendingReward: Int = accumulatedReward - userInfo.rewardDebt;

let ctx: Context = context();
let sendBackTon: Int = ctx.value - gasConsumption;
if (_pendingReward <= 0) {
throw(ERROR_NO_REWARD);
userInfo.amount = userInfo.amount - msg.withdrawAmount;
userInfo.rewardDebt = userInfo.rewardDebt - msg.withdrawAmount * msg.accRewardPerShare / ACC_PRECISION;
// Send Withdraw Internal
self.userInfo.set(msg.lpTokenAddress, userInfo);

send(SendParameters{
to: self.masterChef,
value: sendBackTon,
mode: 0,
body: WithdrawAndHarvestReply{
queryId: msg.queryId,
lpTokenAddress: msg.lpTokenAddress,
rewardAmount: 0,
withdrawAmount: msg.withdrawAmount,
sender: self.owner,
beneficiary: msg.beneficiary
}.toCell()
});
return ;
}
userInfo.rewardDebt = accumulatedReward - msg.withdrawAmount * msg.accRewardPerShare;
userInfo.amount = userInfo.amount - msg.withdrawAmount;
Expand All @@ -105,8 +132,8 @@ contract MiniChef with Deployable {
// Send WithdrawAndHarvestReply to MasterChef
send(SendParameters{
to: self.masterChef,
value: 0,
mode: SendRemainingValue,
value: sendBackTon,
mode: 0,
body: WithdrawAndHarvestReply{
queryId: msg.queryId,
lpTokenAddress: msg.lpTokenAddress,
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions contracts/jetton.tact → contracts/packages/mock/jetton.tact
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "@stdlib/deploy";
import "./packages/token/jetton/JettonMaster";
import "./packages/token/jetton/JettonWallet";
import "./JettonMaster";
import "./JettonWallet";

contract JettonWalletUSDT with JettonWallet {
balance: Int as coins = 0;
Expand Down
Loading

0 comments on commit 8b55db9

Please sign in to comment.