contract: ct_2sd6oH5kfwh9KoLFi4fTyfJQ9akJs98fuJBK6abM7P65rxsAcR

Contract source code
The code as it had been recorded in the contract create transaction. This is not being validated if it matches the bytecode.
include "List.aes"
include "Pair.aes"
namespace Worker =
  type package_code = string

  record package = {
    daily_cap : int,
    price : int}

  record aggregated_package = {
    daily_cap : int,
    count : int}

  record worker = {
    daily_cap : int,
    can_withdraw_payout : bool,
    packages : map(package_code, aggregated_package),
    joined_pool_tmst : int}

  record transfer_packs =
    {
     worker : address,
     packages_to_move : list(string * int),
     new_address : address
     }

  datatype approvable_action = Transfer(transfer_packs)

  function new_package(price : int, cap : int) : package =
    {daily_cap = cap,
     price = price}

  function claim(ps : list(package_code * (package * int)), joined_tmst : int) : worker =
    let daily_cap = daily_cap_from_packs_list(ps) 
    let packs : map(package_code, aggregated_package) =
      List.foldl(
        (accum, t) =>
          let pack_id = Pair.fst(t)
          let (pack, cnt) = Pair.snd(t)
          let val =
            switch(Map.lookup(pack_id, accum))
              None => {daily_cap = pack.daily_cap, count = cnt}
              Some(v) => v{count = v.count + cnt}
          accum{[pack_id] = val},
        {},
        ps)
    {daily_cap = daily_cap,
     can_withdraw_payout = false,
     packages = packs,
     joined_pool_tmst = joined_tmst}

  function split_packages(w : worker, split : transfer_packs) : worker * worker =
    let (packages_left, packages_collected) =
      List.foldl(
        (accum, p) =>
          let accum_left = Pair.fst(accum)
          let accum_collected = Pair.snd(accum)
          let code = Pair.fst(p)
          let count = Pair.snd(p)
          switch(Map.lookup(code, accum_left))
            None => abort("Does not own enough packages")
            Some(owned_packs) =>
              let left_packs = owned_packs.count - count 
              require(left_packs > -1, "Does not own enough packages")
              (accum_left{[code] = owned_packs{count = left_packs}}, (code, owned_packs{count = count}) :: accum_collected),
        (w.packages, []),
        split.packages_to_move)
    let daily_cap_delta = List.sum(List.map((t) => Pair.snd(t).daily_cap * Pair.snd(t).count, packages_collected))
    let new_w = {daily_cap = daily_cap_delta,
                 can_withdraw_payout = false,
                 packages = Map.from_list(packages_collected),
                 joined_pool_tmst = Chain.block_height}
    require(Map.size(new_w.packages) == List.length(packages_collected), "Do not split counts of the same package code")
    (w{daily_cap = w.daily_cap - daily_cap_delta, packages = packages_left}, new_w)

  function merge_workers(w1 : worker, w2: worker) =
    let packages =
      List.foldl(
        (accum, t) =>
          let code = Pair.fst(t)
          let aggr_pack = Pair.snd(t)
          let updated_pack =
            switch(Map.lookup(code, accum))
              None => aggr_pack
              Some(p) => p{count = p.count + aggr_pack.count}
          accum{[code] = updated_pack},
        w1.packages,
        Map.to_list(w2.packages))
    // if one of them is allowed to withdraw, so is the resulting new account
    let oldest_tmst =
      switch(w1.joined_pool_tmst < w2.joined_pool_tmst)
        true => w1.joined_pool_tmst
        false => w2.joined_pool_tmst
    let can_withdraw_payout = w1.can_withdraw_payout || w2.can_withdraw_payout
    let daily_cap = daily_cap_from_packages(packages) 
    {daily_cap = daily_cap,
     can_withdraw_payout = can_withdraw_payout,
     packages = packages,
     joined_pool_tmst = oldest_tmst}

  function daily_cap_from_packs_list(ps : list(package_code * (package * int))) =
    List.sum(List.map((t) => Pair.fst(Pair.snd(t)).daily_cap * Pair.snd(Pair.snd(t)), ps))
                
  function daily_cap_from_packages(ps : map(package_code, aggregated_package)) =
    List.sum(List.map((t) => Pair.snd(t).daily_cap * Pair.snd(t).count, Map.to_list(ps)))





contract interface Data =
  stateful entrypoint set_hive : (address) => unit
  stateful entrypoint add : (address, Worker.worker) => unit
  stateful entrypoint remove : (address) => unit
  payable stateful entrypoint give_rewards : (list(address * int)) => unit
  entrypoint balance : (address) => int
  entrypoint assert_is_payable : (address) => unit
  stateful entrypoint payout : () => unit
  stateful entrypoint payout_without_payable_check : (address) => unit
  entrypoint all_balances : () => list(address * int)
  entrypoint all_daily_caps : () => list(address * int)
  entrypoint all : () => list(address)
  entrypoint all_detailed : () => map(address, Worker.worker)
  entrypoint member : (address) => bool
  entrypoint get : (address) => Worker.worker
  stateful entrypoint rename : (address, address) => unit
  stateful entrypoint make_payable : (address) => unit
  stateful entrypoint make_non_payable : (address) => unit
  stateful entrypoint split_packages : (Worker.transfer_packs) => unit
  entrypoint all_balances_and_daily_caps : () => list(address * int * int)

contract interface Hive =
  entrypoint leader : () => address
  stateful entrypoint enroll : (address, Worker.worker) => unit
  entrypoint member : (address) => bool
  stateful entrypoint remove : (address) => unit
  entrypoint get : (address) => Worker.worker
  stateful entrypoint set_locked : (bool) => unit
  stateful entrypoint set_leader : (address) => unit
  entrypoint can_be_destroyed : () => bool
  entrypoint info : () => address * string * address * string * string * string * string * list(string)
  stateful entrypoint make_payable : (address) => unit
  stateful entrypoint make_non_payable : (address) => unit
  entrypoint assert_worker_is_payable : (address) => unit
  stateful entrypoint force_payout : (address) => unit
  stateful entrypoint change_worker_address : (address, address) => unit
  entrypoint balance : (address) => int
  stateful entrypoint set_data_ct : (Data) => unit
  stateful entrypoint move_data_and_coins_to_new_hive : (Hive) => Data
  payable entrypoint receive_coins : () => unit 
  stateful entrypoint evacuate_coins : (int, address) => unit
  stateful entrypoint split_packages : (Worker.transfer_packs) => unit


include "List.aes"
include "Pair.aes"


main contract HiveData:Data =
  record state =
    { 
      workers : map(address, Worker.worker),
      hive_ct : address,
      balances : map(address, int)
    }

  entrypoint init(hive : address) =
    {workers = {},
     hive_ct = hive,
     balances = {}}
  
  stateful entrypoint set_hive(hive_ct : address) =
    assert_caller_is_hive_contract()
    put(state{hive_ct = hive_ct})

  stateful entrypoint add(worker_address : address, worker : Worker.worker) =
    assert_caller_is_hive_contract()
    switch(Map.lookup(worker_address, state.workers))
      None =>
        put(state{workers[worker_address] = worker})
      Some(old_worker) =>
        put(state{workers[worker_address] = Worker.merge_workers(worker, old_worker)})

  /* deletes a worker from the hive if present. Currently the accumulated coins remain in
     hive. */
  stateful entrypoint remove(worker_address : address) =
    assert_caller_is_hive_contract()
    put(state{workers = Map.delete(worker_address, state.workers)})

  payable stateful entrypoint give_rewards(rewards : list(address * int )) =
    assert_caller_is_hive_contract()
    List.foreach(rewards, give_reward)

  entrypoint balance(worker_address : address) =
    switch(Map.lookup(worker_address, state.balances))
      None => 0 
      Some(balance) => balance

  entrypoint assert_is_payable(worker_addr : address) =
    let worker = get(worker_addr)
    require(worker.can_withdraw_payout, "Not allowed to withdraw")

  stateful entrypoint payout() =
    assert_is_payable(Call.origin)
    payout_without_payable_check(Call.origin)

  stateful entrypoint payout_without_payable_check(worker_addr) =
    assert_caller_is_hive_contract()
    switch(balance(worker_addr))
      0 => abort("No balance")
      balance =>
        Chain.spend(Call.origin, balance)
        put(state{balances = Map.delete(Call.origin, state.balances)})

  entrypoint all_balances() : list(address * int) =
    Map.to_list(state.balances)

  entrypoint all_daily_caps() : list(address * int) =
    List.map((kv) =>
                let worker = Pair.snd(kv)
                (Pair.fst(kv), worker.daily_cap),
        Map.to_list(state.workers))

  entrypoint all_balances_and_daily_caps() : list(address * int * int) =
    List.map((kv) =>
                let worker = Pair.snd(kv)
                let balance = balance(Pair.fst(kv))
                (Pair.fst(kv), balance, worker.daily_cap),
        Map.to_list(state.workers))

  entrypoint all() : list(address) =
    map_keys(state.workers)

  entrypoint all_detailed() : map(address, Worker.worker) =
    state.workers

  entrypoint member(worker_address : address) : bool =
    Map.member(worker_address, state.workers)

  stateful entrypoint rename(old_addr : address, new_addr : address) =
    assert_caller_is_hive_contract() 
    put(state{workers = rename_key(old_addr, new_addr, state.workers),
              balances = rename_key(old_addr, new_addr, state.balances)})

  entrypoint get(worker_address : address) =
    switch(Map.lookup(worker_address, state.workers))
      None => abort("Unknown worker")
      Some(worker) => worker

  function assert_caller_is_hive_contract() =
    require(Call.caller == state.hive_ct, "Call it through the hive contract")

  stateful function give_reward((worker_address : address, reward : int)) =
    assert_caller_is_hive_contract()
    let old_balance = balance(worker_address)
    put(state{balances[worker_address] = old_balance + reward})

  stateful entrypoint make_payable(worker_address : address) =
    assert_caller_is_hive_contract()
    let worker = get(worker_address)
    let validated_worker = worker{can_withdraw_payout = true}
    put(state{workers[worker_address] = validated_worker})

  stateful entrypoint make_non_payable(worker_address : address) =
    assert_caller_is_hive_contract()
    let worker = get(worker_address)
    let unvalidated_worker = worker{can_withdraw_payout = false}
    put(state{workers[worker_address] = unvalidated_worker})

  stateful entrypoint split_packages(split : Worker.transfer_packs) =
    assert_caller_is_hive_contract()
    let worker = get(split.worker)
    let (worker_updated, new_worker) = Worker.split_packages(worker, split)
    let new_worker1 =
      switch(Map.lookup(split.new_address, state.workers))
        None => new_worker
        Some(old_new_worker) => Worker.merge_workers(new_worker, old_new_worker)
    put(state{workers = state.workers{[split.worker] = worker_updated, [split.new_address] = new_worker1}})

  function map_keys(map) =
    List.map((kv) => Pair.fst(kv), Map.to_list(map))

  function rename_key(old_key, new_key, map) =
    switch(Map.lookup(old_key, map))
      None => map
      Some(value) =>
        let map1 = Map.delete(old_key, map)
        map1{[new_key] = value}