sophia/test/contracts/fundme.aes
2018-12-22 01:23:40 +01:00

66 lines
2.0 KiB
Plaintext

/*
* A simple crowd-funding example
*/
contract FundMe =
record spend_args = { recipient : address,
amount : int }
record state = { contributions : map(address, int),
total : int,
beneficiary : address,
deadline : int,
goal : int }
private function require(b : bool, err : string) =
if(!b) abort(err)
private function spend(args : spend_args) =
Chain.spend(args.recipient, args.amount)
public function init(beneficiary, deadline, goal) : state =
{ contributions = {},
beneficiary = beneficiary,
deadline = deadline,
total = 0,
goal = goal }
private function is_contributor(addr) =
Map.member(addr, state.contributions)
public stateful function contribute() =
if(Chain.block_height >= state.deadline)
spend({ recipient = Call.caller, amount = Call.value }) // Refund money
false
else
let amount =
Map.lookup_default(Call.caller, state.contributions, 0) + Call.value
put(state{ contributions[Call.caller] = amount,
total @ tot = tot + Call.value })
true
public stateful function withdraw() =
if(Chain.block_height < state.deadline)
abort("Cannot withdraw before deadline")
if(Call.caller == state.beneficiary)
withdraw_beneficiary()
elif(is_contributor(Call.caller))
withdraw_contributor()
else
abort("Not a contributor or beneficiary")
private stateful function withdraw_beneficiary() =
require(state.total >= state.goal, "Project was not funded")
spend({recipient = state.beneficiary,
amount = Contract.balance })
put(state{ beneficiary = #0 })
private stateful function withdraw_contributor() =
if(state.total >= state.goal)
abort("Project was funded")
let to = Call.caller
spend({recipient = to,
amount = state.contributions[to]})
put(state{ contributions @ c = Map.delete(to, c) })