import "constants"; import "messages"; fun stakingDepositMessage(value: Int, pool: Address): SendParameters { return SendParameters{ to: pool, value: value, body: beginCell().storeUint(0x7bcd1fef, 32)/*.storeSlice("Deposit".asSlice())*/.endCell() }; } fun stakingWithdrawMessage(value: Int, pool: Address): SendParameters { return SendParameters{ to: pool, value: ton("0.05"), body: beginCell().storeUint(3665837821, 32).storeCoins(value).endCell() }; } struct WithdrawalRequests { addresses: map[Int]Address; amounts: map[Int]Int; n_requests: Int = 0; } fun withdrawalSum(requests: WithdrawalRequests): Int { let sum: Int = 0; let i: Int = 0; while(i < requests.n_requests) { sum = sum + requests.amounts.get(i)!!; i = i + 1; } return sum; } trait StakingTrait { staking_pool: Address?; withdrawal_requests: WithdrawalRequests; owner: Address; in_the_pool: Int = 0; fun sendStake() { if(self.staking_pool == null) { return; } let value: Int = myBalance() - tonb_floor - staking_gas; if(value < ton("0.05")) { return; } self.in_the_pool = self.in_the_pool + value; send(stakingDepositMessage(value, self.staking_pool!!)); } fun sendWithdrawal() { if(self.staking_pool == null) { return; } let value: Int = withdrawalSum(self.withdrawal_requests); send(stakingWithdrawMessage(value, self.staking_pool!!)); } receive("Withdraw completed") { let i: Int = 0; while(i < self.withdrawal_requests.n_requests) { let addr: Address = self.withdrawal_requests.addresses.get(i)!!; send(SendParameters{ to: addr, value: ton("0.08"), bounce: false, body: TokenBurn{ amount: self.withdrawal_requests.amounts.get(i)!!, queryId: 0, responseAddress: myAddress(), owner: addr }.toCell() }); i = i + 1; } let ctx: Context = context(); let val: Int = ctx.value; self.in_the_pool = self.in_the_pool - val; if (self.in_the_pool < 0) { let value: Int = -self.in_the_pool; send(SendParameters{ to: self.owner, value: value, body: Unstake{amount: value}.toCell() }); self.in_the_pool = 0; } self.withdrawal_requests = WithdrawalRequests{ addresses: emptyMap(), amounts: emptyMap() }; } receive(msg: Unstake) { if(self.staking_pool == null) { return; } let ctx: Context = context(); require(ctx.sender == self.owner, "Only the owner can trigger un-staking"); send(stakingWithdrawMessage(msg.amount /* 0 to unstake all */, self.staking_pool!!)); } fun requestWithdrawal(address: Address, value: Int) { self.withdrawal_requests.addresses.set(self.withdrawal_requests.n_requests, address); self.withdrawal_requests.amounts.set(self.withdrawal_requests.n_requests, value); self.withdrawal_requests.n_requests = self.withdrawal_requests.n_requests + 1; send(stakingWithdrawMessage(value, self.staking_pool!!)); } }