Skip to content

Instantly share code, notes, and snippets.

@owen9825
Created January 13, 2022 20:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save owen9825/e3c3265013c678b5f06be1b176af29c5 to your computer and use it in GitHub Desktop.
Save owen9825/e3c3265013c678b5f06be1b176af29c5 to your computer and use it in GitHub Desktop.
Tezos contract for splitting contracts to multiple recipients
type shareholder_ledger = (address, nat) big_map (** ℕ *)
type recipient_withdrawals = (address, tez) big_map (** µꜩ *)
type contract_storage =
[@layout:comb]
{
shareholders: shareholder_ledger;
withdrawals: recipient_withdrawals;
total_shares: nat;
total_withdrawn: tez; (** µꜩ *)
}
let record_withdrawal (recipient, shares, storage : address * nat * contract_storage)
: tez * contract_storage =
let existing_debit : tez =
match Big_map.find_opt recipient storage.withdrawals with
| None -> 0mutez
| Some ed -> ed
// https://tezosacademy.io/reason/chapter-built-ins
in let new_payment: tez = (((Tezos.balance + storage.total_withdrawn) * shares) / storage.total_shares) - existing_debit
in let _void: unit =
if new_payment <= 0mutez
then failwith "No more remains for this recipient"
else ()
in let new_withdrawals: recipient_withdrawals =
Big_map.update recipient (Some (new_payment + existing_debit)) storage.withdrawals
in let new_storage = { storage with withdrawals = new_withdrawals;
total_withdrawn = storage.total_withdrawn + new_payment}
in new_payment, new_storage
(**
We have to keep the recipients separate, because sending to one recipient could cause
undesirable execution. See https://ligolang.org/docs/tutorials/security/security/#transactions-to-untrusted-contracts
*)
let withdraw(recipient, storage: address * contract_storage)
: (operation list) * contract_storage =
let shares : nat =
match Big_map.find_opt recipient storage.shareholders with
| None -> failwith "Not a shareholder"
| Some s -> s
in let new_payment, new_storage : tez * contract_storage = record_withdrawal(recipient, shares, storage)
// https://tezosacademy.io/camel/chapter-transactions
in let destination: unit contract =
match (Tezos.get_contract_opt (recipient): unit contract option) with
| Some contract -> contract
| None -> (failwith "Nothing found at destination address" : unit contract)
in let transferred = Tezos.transaction unit new_payment destination in
([transferred], new_storage)
type entrypoint =
[@layout:comb]
| Withdraw of address
| Default of unit
let main (param, storage : entrypoint * contract_storage) : operation list * contract_storage =
match param with
| Withdraw recipient ->
let () = if Tezos.amount > 0tez
then failwith "If you'd like to send funds; you're invoking the wrong function"
in withdraw(recipient, storage)
| Default _d -> ([]: operation list), storage
@owen9825
Copy link
Author

This code was deployed to https://tzkt.io/KT1UMeW6AW2Jf67TM8ts5TkBEQnVBUh8FuXF/code using the Ligo compiler 5875d8333e882499da3b49c16e288dd7228ffe9c from 2021-12-17T05:38:57+00:00.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment