new NonNegativeNumber in { contract NonNegativeNumber(@init, return) = { new this, valueStore in { contract this(@"add", @x, success) = { if (x >= 0) { for(@v <- valueStore){ if (v + x > v) { valueStore!(v + x) | success!(true) } else { //overflow valueStore!(v) | success!(false) } } } else { success!(false) } } | contract this(@"sub", @x, success) = { if (x >= 0) { for(@v <- valueStore) { if (x <= v) { valueStore!(v - x) | success!(true) } else { valueStore!(v) | success!(false) } } } else { success!(false) } } | contract this(@"value", return) = { for(@v <- valueStore) { valueStore!(v) | return!(v) } } | return!(bundle+{*this}) | if (init >= 0) { valueStore!(init) } else { valueStore!(0) } //Initial balance is zero if given is negative} } } | new MakeMint in { contract MakeMint(return) = { new thisMint, internalMakePurse, decr in { contract thisMint(@"makePurse", @init, return) = { new balanceCh in { // initialize NonNegativeNumber, living on the name balance. NonNegativeNumber!(init, *balanceCh) | for(@balance <- balanceCh) { internalMakePurse!(balance, *return) } } } | // since balance is a NonNegativeNumber, it exposes all the methods of NN contract internalMakePurse(balance, return) = { //balance must be a name that NonNegativeNumber contract is listening on new thisPurse in { contract thisPurse(@=*decr, @amount, success) = { balance!("sub", amount, *success) } | contract thisPurse(@"getBalance", return) = { balance!("value", *return) } | contract thisPurse(@"sprout", return) = { thisMint!("makePurse", 0, *return) } | contract thisPurse(@"split", @amount, return) = { new destPurseCh, successCh in { thisPurse!("sprout", *destPurseCh) | for(@destPurse <- destPurseCh) { @destPurse!("deposit", amount, *thisPurse, *successCh) | for(@success <- successCh) { if (success) { return!([destPurse]) } else { return!([]) } } } } } | contract thisPurse(@"deposit", @amount, @src, success) = { new result in { balance!("add", amount, success) | for(addSuccess <- success) { if(addSuccess) { @src!(*decr, amount, *result) | //call src decr function. for(@decrSuccess <- result) { if (decrSuccess) { success!(true) } else { success!(false) | balance!("sub", amount, Nil) } } } else { success!(false) } } } } | return!(bundle+{*thisPurse}) } } | return!(bundle+{*thisMint}) } } } }