scilla_version 0 import BoolUtils IntUtils ListUtils PairUtils library StakingContract type Denom = | Zil | Token of ByStr20 type Coins = | Coins of Denom Uint128 type RewardParam = | RewardParam of Uint128 Uint128 Uint64 Uint64 type Stake = | Stake of Uint128 Uint64 Uint64 Uint128 type RewardResult = | RewardResult of Uint128 Uint128 let fee_denom = Uint256 10000 let zil_address = 0x0000000000000000000000000000000000000000 let bool_active = True let bool_inactive = False let zil = Zil let zero = Uint128 0 let zero_i256 = Int256 0 let min_bps = Uint128 1 let max_bps = Uint128 10000 let seconds_per_year = Uint128 31536000 let true = True let one_msg = fun (m : Message) => let e = Nil {(Message)} in Cons {(Message)} m e type Error = | CodeNotOwner | ContractFrozenFailure | Unauthorized | ContractFrozenFailurePaused | ContractFrozenFailureNotPaused | RewardTokenNotFound | NoStakeFoundBySender | AmountGreaterThanStakedAmount | NotAllowedToWithdrawStakeTokens | InvalidBPSError | CodeInsufficientFunds let make_error = fun (result : Error) => let result_code = match result with | CodeNotOwner => Int32 -1 | ContractFrozenFailure => Int32 -2 | Unauthorized => Int32 -3 | ContractFrozenFailurePaused => Int32 -4 | ContractFrozenFailureNotPaused => Int32 -5 | RewardTokenNotFound => Int32 -6 | NoStakeFoundBySender => Int32 -7 | AmountGreaterThanStakedAmount => Int32 -8 | NotAllowedToWithdrawStakeTokens => Int32 -9 | InvalidBPSError => Int32 -10 | CodeInsufficientFunds => Int32 -11 end in { _exception : "Error"; code : result_code } let get_value = fun (var : Option Uint128) => match var with | Some v => v | None => zero end let uint64_to_uint128 : Uint64 -> Uint128 = fun (x : Uint64) => let ox128 = builtin to_uint128 x in match ox128 with | None => let zero = Uint128 0 in builtin div zero zero | Some x128 => x128 end let int256_to_uint128 : Int256 -> Uint128 = fun (x : Int256) => let ox128 = builtin to_uint128 x in match ox128 with | None => let zero = Uint128 0 in builtin div zero zero | Some x128 => x128 end let is_admin_or_owner : (Map ByStr20 Bool) -> ByStr20 -> ByStr20 -> Bool = fun (administrators : Map ByStr20 Bool) => fun (owner : ByStr20) => fun (sender : ByStr20) => let is_admin = builtin contains administrators sender in let is_owner = builtin eq sender owner in let allowed = orb is_admin is_owner in match allowed with | True => True | False => False end let update_reward_param : RewardParam -> Uint64 -> RewardParam = fun (reward_param : RewardParam) => fun (current_timestamp : Uint64) => match reward_param with | RewardParam apr treasury_fee start_timestamp end_timestamp => let zero_timestamp = Uint64 0 in let is_eq_timestamp_zero = builtin eq end_timestamp zero_timestamp in match is_eq_timestamp_zero with | True => RewardParam apr treasury_fee start_timestamp current_timestamp | False => RewardParam apr treasury_fee start_timestamp end_timestamp end end let update_all_reward_params : forall 'A. (List RewardParam) -> Uint64 -> List RewardParam = tfun 'A => fun (l : List RewardParam) => fun (current_timestamp : Uint64) => let foldl = @list_foldl (RewardParam) (List RewardParam) in let init = Nil {(RewardParam)} in let iter = fun (reward_params_list : List RewardParam) => fun (reward_param : RewardParam) => let updated_reward_param = update_reward_param reward_param current_timestamp in Cons {(RewardParam)} updated_reward_param reward_params_list in foldl iter init l let is_timestamp_let : Uint64 -> Uint64 -> Bool = fun (ts1 : Uint64) => fun (ts2 : Uint64) => let is_ts1_le_ts2 = uint64_lt ts1 ts2 in let is_ts1_eq_ts2 = builtin eq ts1 ts2 in orb is_ts1_le_ts2 is_ts1_eq_ts2 let get_time_difference : Uint128 -> Uint64 -> RewardParam -> Uint64 -> Uint64 = fun (staked_amount : Uint128) => fun (staked_timestamp : Uint64) => fun (reward_param : RewardParam) => fun (current_timestamp : Uint64) => match reward_param with | RewardParam apr treasury_fee start_timestamp end_timestamp => let zero_timestamp = Uint64 0 in let microseconds = Uint64 1000000 in let is_eq_block_zero = builtin eq end_timestamp zero_timestamp in match is_eq_block_zero with | True => let is_staked_timestamp_leq_start_timestamp = is_timestamp_let staked_timestamp start_timestamp in match is_staked_timestamp_leq_start_timestamp with | True => let diff = builtin sub current_timestamp start_timestamp in builtin div diff microseconds | False => let diff = builtin sub current_timestamp staked_timestamp in builtin div diff microseconds end | False => let is_staked_timestamp_leq_end_timestamp = is_timestamp_let staked_timestamp end_timestamp in match is_staked_timestamp_leq_end_timestamp with | True => let is_staked_timestamp_leq_start_timestamp = is_timestamp_let staked_timestamp start_timestamp in match is_staked_timestamp_leq_start_timestamp with | True => let diff = builtin sub end_timestamp start_timestamp in builtin div diff microseconds | False => let diff = builtin sub end_timestamp staked_timestamp in builtin div diff microseconds end | False => zero_timestamp end end end let uint128_to_uint256 : Uint128 -> Uint256 = fun (x : Uint128) => let ox256 = builtin to_uint256 x in match ox256 with | None => let zero = Uint256 0 in builtin div zero zero | Some x256 => x256 end let muldiv : Uint128 -> Uint128 -> Uint128 -> Uint128 -> Uint256 -> Uint128 = fun (w : Uint128) => fun (x : Uint128) => fun (y : Uint128) => fun (z : Uint128) => fun (f : Uint256) => let w256 = uint128_to_uint256 w in let x256 = uint128_to_uint256 x in let y256 = uint128_to_uint256 y in let z256 = uint128_to_uint256 z in let w_mul_x256 = builtin mul w256 x256 in let w_mul_x_mul_y256 = builtin mul w_mul_x256 y256 in let w_mul_x_mul_y256_div_z256 = builtin div w_mul_x_mul_y256 z256 in let res256 = builtin div w_mul_x_mul_y256_div_z256 f in let ores128 = builtin to_uint128 res256 in match ores128 with | None => let max_uint128 = Uint128 340282366920938463463374607431768211455 in let fourtytwo128 = Uint128 42 in builtin mul max_uint128 fourtytwo128 | Some res128 => res128 end let calculate_treasury_fee_amt : Uint128 -> Uint256 -> Uint128 -> Uint128 = fun (treasury_fee : Uint128) => fun (fee_denom : Uint256) => fun (amount : Uint128) => let tf256 = uint128_to_uint256 treasury_fee in let amt256 = uint128_to_uint256 amount in let tf_mul_amt = builtin mul tf256 amt256 in let res256 = builtin div tf_mul_amt fee_denom in let ores128 = builtin to_uint128 res256 in match ores128 with | None => let max_uint128 = Uint128 340282366920938463463374607431768211455 in let fourtytwo128 = Uint128 42 in builtin mul max_uint128 fourtytwo128 | Some res128 => res128 end let calculate_rewards : forall 'A. (List RewardParam) -> Uint128 -> Uint64 -> Uint64 -> Uint128 -> Uint256 -> RewardResult = tfun 'A => fun (l : List RewardParam) => fun (staked_amount : Uint128) => fun (staked_timestamp : Uint64) => fun (current_timestamp : Uint64) => fun (seconds_per_year : Uint128) => fun (fee_denom : Uint256) => let foldl = @list_foldl (RewardParam) (RewardResult) in let init = RewardResult zero zero in let iter = fun (rewards : RewardResult) => fun (reward_param : RewardParam) => match reward_param with | RewardParam apr treasury_fee start_block end_block => let time_diff_ui64 = get_time_difference staked_amount staked_timestamp reward_param current_timestamp in let time_diff = uint64_to_uint128 time_diff_ui64 in let res_total = muldiv staked_amount time_diff apr seconds_per_year fee_denom in let treasury_fee_amt = calculate_treasury_fee_amt treasury_fee fee_denom res_total in let res = builtin sub res_total treasury_fee_amt in match rewards with | RewardResult curr_rewards_count curr_treasury_fee_amt => let new_rewards_count = builtin add curr_rewards_count res in let new_treasury_fee_amt = builtin add curr_treasury_fee_amt treasury_fee_amt in RewardResult new_rewards_count new_treasury_fee_amt end end in foldl iter init l let portion = fun (amount : Uint128) => fun (bps : Uint128) => let max_bps = Uint128 10000 in let x = builtin div max_bps bps in let result = builtin div amount x in result let option_value = tfun 'A => fun (default : 'A) => fun (maybe_val : Option 'A) => match maybe_val with | Some v => v | None => default end let option_timestamp = @option_value (Uint64) let get_prev_bnum = fun (cur_blk : BNum) => let one_bnum = BNum 1 in let zero_block = BNum 0 in let prev_block = builtin bsub cur_blk one_bnum in let prev_block_uint128 = int256_to_uint128 prev_block in builtin badd zero_block prev_block_uint128 contract StakingContract ( initial_owner : ByStr20, initial_staking_token_address : ByStr20 with contract field allowances : Map ByStr20 (Map ByStr20 Uint128), field balances : Map ByStr20 Uint128, field total_supply : Uint128 end ) field owner : ByStr20 = initial_owner field staking_token_address : ByStr20 = initial_staking_token_address field pending_owner : ByStr20 = zil_address field paused : Bool = True field reward_pairs : Map ByStr20 (List RewardParam) = Emp (ByStr20) (List RewardParam) field stakes : Map ByStr20 Stake = Emp (ByStr20) (Stake) field rewards : Map ByStr20 (Map ByStr20 Uint128) = Emp (ByStr20) (Map ByStr20 Uint128) field administrators : Map ByStr20 Bool = Emp (ByStr20) (Bool) field treasury_balances : Map ByStr20 Uint128 = Emp (ByStr20) (Uint128) field treasury_fees_address : ByStr20 = initial_owner field penalty_fee_balances : Uint128 = zero field total_staked_amount : Uint128 = zero procedure Throw (err : Error) e = make_error err; throw e end procedure EnsureContractIsNotPaused () paused_tmp <- paused; match paused_tmp with | False => | True => err = ContractFrozenFailurePaused; Throw err end end procedure EnsureContractIsPaused () paused_tmp <- paused; match paused_tmp with | False => err = ContractFrozenFailureNotPaused; Throw err | True => end end procedure EnsureSenderIsOwner (initiator : ByStr20) current_owner <- owner; is_owner = builtin eq initiator current_owner; match is_owner with | True => | False => err = CodeNotOwner; Throw err end end procedure EnsureSenderIsAdminOrOwner (address : ByStr20) admins <- administrators; current_owner <- owner; check_allowed = is_admin_or_owner admins current_owner address; match check_allowed with | True => | False => err = Unauthorized; Throw err end end procedure EnsureNotStakeToken (address : ByStr20) stake_token_addr <- staking_token_address; is_same = builtin eq address stake_token_addr; match is_same with | True => err = NotAllowedToWithdrawStakeTokens; Throw err | False => end end procedure RequireValidBPS (val_bps : Uint128) is_gte_min = uint128_ge val_bps min_bps; is_lte_max = uint128_le val_bps max_bps; is_valid = andb is_gte_min is_lte_max; match is_valid with | True => | False => error = InvalidBPSError; Throw error end end procedure Send (coins : Coins, to_address : ByStr20) match coins with | Coins denom amount => match denom with | Zil => msg = { _tag : "AddFunds"; _recipient : to_address; _amount : amount }; msgs = one_msg msg; send msgs | Token token => msg_to_token = { _tag : "Transfer"; _recipient : token; _amount : zero; to : to_address; amount : amount }; msgs = one_msg msg_to_token; send msgs end end end procedure Receive (coins : Coins, initiator : ByStr20) EnsureContractIsNotPaused; match coins with | Coins denom amount => match denom with | Zil => needs_refund = uint128_gt _amount amount; accept; match needs_refund with | True => refund = let refund_amount = builtin sub _amount amount in Coins zil refund_amount; Send refund initiator | False => end | Token token => msg_to_token = { _tag : "TransferFrom"; _recipient : token; _amount : zero; from : initiator; to : _this_address; amount : amount }; msgs = one_msg msg_to_token; send msgs end end end procedure UpdateTreasuryFeeAmount (reward_token : ByStr20, amount : Uint128) is_amount_eq_zero = builtin eq amount zero; match is_amount_eq_zero with | False => maybe_treasury_fee_amount <- treasury_balances[reward_token]; match maybe_treasury_fee_amount with | Some curr_amount => new_amount = builtin add curr_amount amount; treasury_balances[reward_token] := new_amount; e = { _eventname : "UpdateTreasuryFeeAmountWithPreviousValueSuccess"; sender : _origin; reward_token : reward_token; old_amount : curr_amount; new_amount : new_amount; difference : amount }; event e | None => treasury_balances[reward_token] := amount; e = { _eventname : "UpdateRewardsAmountFirstClaimSuccess"; sender : _origin; reward_token : reward_token; new_amount : amount }; event e end | True => end end procedure UpdateRewardsAmount (reward_token : ByStr20, amount : Uint128) is_amount_eq_zero = builtin eq amount zero; match is_amount_eq_zero with | False => maybe_rewards_amount <- rewards[reward_token][_origin]; match maybe_rewards_amount with | Some curr_amount => new_amount = builtin add curr_amount amount; rewards[reward_token][_origin] := new_amount; e = { _eventname : "UpdateRewardsAmountWithPreviousValueSuccess"; sender : _origin; reward_token : reward_token; old_amount : curr_amount; new_amount : new_amount; difference : amount }; event e | None => rewards[reward_token][_origin] := amount; e = { _eventname : "UpdateRewardsAmountFirstClaimSuccess"; sender : _origin; reward_token : reward_token; new_amount : amount }; event e end | True => end end procedure UpdateRewards (reward_token : ByStr20, reward_res : RewardResult) match reward_res with | RewardResult total_rewards treasury_fee_amt => UpdateRewardsAmount reward_token total_rewards; UpdateTreasuryFeeAmount reward_token treasury_fee_amt end end procedure DoClaimRewards (reward_pair : Pair ByStr20 (List RewardParam)) maybe_stake <- stakes[_origin]; current_block <-& BLOCKNUMBER; prev_block = get_prev_bnum current_block; ts <-& TIMESTAMP(prev_block); zero_64 = Uint64 0; current_timestamp = option_timestamp zero_64 ts; match maybe_stake with | Some stake => match stake with | Stake staked_amount staked_timestamp end_block penalty_fee => reward_token_address = let fst_reward_token_address = @fst (ByStr20) (List RewardParam) in fst_reward_token_address reward_pair; reward_param_list = let snd_reward_param_list = @snd (ByStr20) (List RewardParam) in snd_reward_param_list reward_pair; calculate_rewards_fun = @calculate_rewards (List RewardParam); maybe_running_interest_amount <- rewards[reward_token_address][_origin]; match maybe_running_interest_amount with | Some running_interest_amount => total_amount = builtin add staked_amount running_interest_amount; reward_res = calculate_rewards_fun reward_param_list total_amount staked_timestamp current_timestamp seconds_per_year fee_denom; UpdateRewards reward_token_address reward_res | None => reward_res = calculate_rewards_fun reward_param_list staked_amount staked_timestamp current_timestamp seconds_per_year fee_denom; UpdateRewards reward_token_address reward_res end end | None => err = NoStakeFoundBySender; Throw err end end procedure DoRemoveRewardToken (reward_token_address : ByStr20) current_block <-& BLOCKNUMBER; prev_block = get_prev_bnum current_block; ts <-& TIMESTAMP(prev_block); zero_64 = Uint64 0; current_timestamp = option_timestamp zero_64 ts; maybe_reward_params_list <- reward_pairs[reward_token_address]; match maybe_reward_params_list with | Some reward_params_list => update_all_reward_params_fun = @update_all_reward_params (List RewardParam); updated_reward_params_list = update_all_reward_params_fun reward_params_list current_timestamp; reward_pairs[reward_token_address] := updated_reward_params_list | None => err = RewardTokenNotFound; Throw err end end procedure DoRemoveAllRewardTokens (reward_pair : Pair ByStr20 (List RewardParam)) reward_token_address = let fst_reward_token_address = @fst (ByStr20) (List RewardParam) in fst_reward_token_address reward_pair; DoRemoveRewardToken reward_token_address end procedure DoWithdrawRewards (reward_pair : Pair ByStr20 (List RewardParam)) reward_token_address = let fst_reward_token_address = @fst (ByStr20) (List RewardParam) in fst_reward_token_address reward_pair; maybe_reward_token_amt <- rewards[reward_token_address][_origin]; match maybe_reward_token_amt with | Some reward_token_amt => is_zil = builtin eq reward_token_address zil_address; match is_zil with | True => stake_token_addr <- staking_token_address; is_staked_token_same_as_withdraw = builtin eq reward_token_address stake_token_addr; match is_staked_token_same_as_withdraw with | True => balances <- _balance; total_staked <- total_staked_amount; available_bal_to_withdraw = builtin sub balances total_staked; is_valid_withdrawal_amount = uint128_le reward_token_amt available_bal_to_withdraw; match is_valid_withdrawal_amount with | True => zils_out = Coins zil reward_token_amt; Send zils_out _origin | False => err = CodeInsufficientFunds; Throw err end | False => zils_out = Coins zil reward_token_amt; Send zils_out _origin end | False => stake_token_addr <- staking_token_address; is_staked_token_same_as_withdraw = builtin eq reward_token_address stake_token_addr; match is_staked_token_same_as_withdraw with | True => balances <-& initial_staking_token_address.balances[_this_address]; contract_balance = get_value balances; total_staked <- total_staked_amount; available_bal_to_withdraw = builtin sub contract_balance total_staked; is_valid_withdrawal_amount = uint128_le reward_token_amt available_bal_to_withdraw; match is_valid_withdrawal_amount with | True => reward_token = Token reward_token_address; tokens_out = Coins reward_token reward_token_amt; Send tokens_out _origin | False => err = CodeInsufficientFunds; Throw err end | False => reward_token = Token reward_token_address; tokens_out = Coins reward_token reward_token_amt; Send tokens_out _origin end end; delete rewards[reward_token_address][_origin]; e = { _eventname : "WithdrawRewardsSuccess"; sender : _origin; reward_token : reward_token_address; amount : reward_token_amt }; event e | None => e = { _eventname : "WithdrawRewardsSuccess"; sender : _origin; reward_token : reward_token_address; amount : zero }; event e end end transition AddStake (amount : Uint128, expiration_time : Uint64, penalty_fee_bps : Uint128) current_block <-& BLOCKNUMBER; prev_block = get_prev_bnum current_block; ts <-& TIMESTAMP(prev_block); zero_64 = Uint64 0; current_timestamp = option_timestamp zero_64 ts; maybe_stake <- stakes[_origin]; RequireValidBPS penalty_fee_bps; token_address <- staking_token_address; token = Token token_address; tokens_in = Coins token amount; Receive tokens_in _origin; match maybe_stake with | Some stake => match stake with | Stake staked_amount timestamp end_timestamp penalty_fee => curent_reward_pairs <- reward_pairs; rewards_list = builtin to_list curent_reward_pairs; forall rewards_list DoClaimRewards; total_amount = builtin add staked_amount amount; updated_stake = Stake total_amount current_timestamp end_timestamp penalty_fee; stakes[_origin] := updated_stake; total_staked <- total_staked_amount; new_total_staked = builtin add total_staked amount; total_staked_amount := new_total_staked end | None => stake = Stake amount current_timestamp expiration_time penalty_fee_bps; stakes[_origin] := stake; total_staked <- total_staked_amount; new_total_staked = builtin add total_staked amount; total_staked_amount := new_total_staked end end transition RemoveStake (amount : Uint128) current_block <-& BLOCKNUMBER; prev_block = get_prev_bnum current_block; ts <-& TIMESTAMP(prev_block); zero_64 = Uint64 0; current_timestamp = option_timestamp zero_64 ts; maybe_stake <- stakes[_origin]; match maybe_stake with | Some (Stake staked_amount staked_timestamp end_timestamp penalty_fee) => is_amount_less_than_staked_amount = builtin lt amount staked_amount; is_amount_equal_to_staked_amount = builtin eq amount staked_amount; is_amount_less_or_equal_to_staked_amount = orb is_amount_less_than_staked_amount is_amount_equal_to_staked_amount; match is_amount_less_or_equal_to_staked_amount with | True => curent_reward_pairs <- reward_pairs; rewards_list = builtin to_list curent_reward_pairs; forall rewards_list DoClaimRewards; is_lt_curr_timestamp = uint64_lt current_timestamp end_timestamp; match is_lt_curr_timestamp with | True => fee_bps = portion amount penalty_fee; new_amount = builtin sub amount fee_bps; penalty_fee_amount <- penalty_fee_balances; new_penalty_fee_amount = builtin add penalty_fee_amount fee_bps; penalty_fee_balances := new_penalty_fee_amount; token_address <- staking_token_address; staked_token = Token token_address; output = Coins staked_token new_amount; Send output _origin | False => token_address <- staking_token_address; staked_token = Token token_address; output = Coins staked_token amount; Send output _origin end; remaining_amount = builtin sub staked_amount amount; is_remaining_amount_eq_zero = builtin eq remaining_amount zero; match is_remaining_amount_eq_zero with | True => delete stakes[_origin] | False => updated_stake = Stake remaining_amount current_timestamp end_timestamp penalty_fee; stakes[_origin] := updated_stake end; total_staked <- total_staked_amount; new_total_staked = builtin sub total_staked amount; total_staked_amount := new_total_staked | False => err = AmountGreaterThanStakedAmount; Throw err end | None => err = NoStakeFoundBySender; Throw err end end transition ClaimRewards () current_block <-& BLOCKNUMBER; prev_block = get_prev_bnum current_block; ts <-& TIMESTAMP(prev_block); zero_64 = Uint64 0; current_timestamp = option_timestamp zero_64 ts; maybe_stake <- stakes[_origin]; match maybe_stake with | Some (Stake staked_amount staked_timestamp end_timestamp penalty_fee) => curent_reward_pairs <- reward_pairs; rewards_list = builtin to_list curent_reward_pairs; forall rewards_list DoClaimRewards; forall rewards_list DoWithdrawRewards; updated_stake = Stake staked_amount current_timestamp end_timestamp penalty_fee; stakes[_origin] := updated_stake | None => curent_reward_pairs <- reward_pairs; rewards_list = builtin to_list curent_reward_pairs; forall rewards_list DoWithdrawRewards end end transition AddRewardToken (reward_token_address : ByStr20, apr : Uint128, treasury_fee : Uint128) EnsureSenderIsAdminOrOwner _sender; current_block <-& BLOCKNUMBER; prev_block = get_prev_bnum current_block; ts <-& TIMESTAMP(prev_block); zero_64 = Uint64 0; current_timestamp = option_timestamp zero_64 ts; end_timestamp = Uint64 0; reward_param = RewardParam apr treasury_fee current_timestamp end_timestamp; maybe_reward_params_list <- reward_pairs[reward_token_address]; match maybe_reward_params_list with | Some reward_params_list => update_all_reward_params_fun = @update_all_reward_params (List RewardParam); updated_reward_params_list = update_all_reward_params_fun reward_params_list current_timestamp; reward_params_list_new = Cons {(RewardParam)} reward_param updated_reward_params_list; reward_pairs[reward_token_address] := reward_params_list_new | None => reward_params_list = Nil {(RewardParam)}; reward_params_list_new = Cons {(RewardParam)} reward_param reward_params_list; reward_pairs[reward_token_address] := reward_params_list_new end end transition RemoveRewardToken (reward_token_address : ByStr20) EnsureSenderIsAdminOrOwner _sender; DoRemoveRewardToken reward_token_address end transition RemoveAllRewardTokens () EnsureSenderIsAdminOrOwner _sender; curent_reward_pairs <- reward_pairs; rewards_list = builtin to_list curent_reward_pairs; forall rewards_list DoRemoveAllRewardTokens end transition Pause () EnsureSenderIsAdminOrOwner _sender; paused := bool_active end transition UnPause () EnsureSenderIsAdminOrOwner _sender; paused := bool_inactive end transition AddAdmin (address : ByStr20) EnsureSenderIsOwner _sender; administrators[address] := true; e = { _eventname : "AddAdminSuccess"; addressAdded : address }; event e end transition RemoveAdmin (address : ByStr20) EnsureSenderIsOwner _sender; delete administrators[address]; e = { _eventname : "RemoveAdminSuccess"; address : address }; event e end transition TransferOwnership (new_owner : ByStr20) EnsureSenderIsOwner _sender; existing_owner <- owner; new_owner_is_existing_owner = builtin eq new_owner existing_owner; match new_owner_is_existing_owner with | True => e = { _exception : "ExistingOwner" }; throw e | False => pending_owner := new_owner end end transition AcceptPendingOwnership () new_owner <- pending_owner; sender_is_pending_owner = builtin eq _sender new_owner; match sender_is_pending_owner with | False => e = { _exception : "InvalidSender" }; throw e | True => owner := new_owner; pending_owner := zil_address; e = { _eventname : "OwnershipTransferred"; owner : new_owner }; event e end end transition WithdrawTokens (token_address : ByStr20, token_amount : Uint128) EnsureSenderIsOwner _sender; stake_token_addr <- staking_token_address; is_staked_token_same_as_withdraw = builtin eq token_address stake_token_addr; match is_staked_token_same_as_withdraw with | True => balances <-& initial_staking_token_address.balances[_this_address]; contract_balance = get_value balances; total_staked <- total_staked_amount; available_bal_to_withdraw = builtin sub contract_balance total_staked; is_valid_withdrawal_amount = uint128_le token_amount available_bal_to_withdraw; match is_valid_withdrawal_amount with | True => reward_token = Token token_address; tokens_out = Coins reward_token token_amount; Send tokens_out _sender | False => err = CodeInsufficientFunds; Throw err end | False => reward_token = Token token_address; tokens_out = Coins reward_token token_amount; Send tokens_out _sender end end transition WithdrawZils (zil_amount : Uint128) EnsureSenderIsAdminOrOwner _sender; zils_out = Coins zil zil_amount; Send zils_out _sender end transition Deposit (token_address : ByStr20, token_amount : Uint128) EnsureSenderIsAdminOrOwner _sender; token = Token token_address; tokens_in = Coins token token_amount; Receive tokens_in _sender end transition TransferFromSuccessCallBack (initiator : ByStr20, sender : ByStr20, recipient : ByStr20, amount : Uint128) end transition TransferSuccessCallBack (sender : ByStr20, recipient : ByStr20, amount : Uint128) end transition RecipientAcceptTransferFrom (initiator : ByStr20, sender : ByStr20, recipient : ByStr20, amount : Uint128) is_valid_transfer_to_self = let self_triggered = builtin eq initiator _this_address in let is_transfer_to_self = builtin eq recipient _this_address in andb self_triggered is_transfer_to_self; match is_valid_transfer_to_self with | False => e = { _exception : "InvalidInvocation" }; throw e | True => end end transition AddFunds () accept end transition RecipientAcceptTransfer (sender : ByStr20, recipient : ByStr20, amount : Uint128) end