-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathoutputxx.json
1 lines (1 loc) · 16.3 KB
/
outputxx.json
1
{"version":21823489,"nonce":43,"toAddr":"0x99ac26ad2868901a11df5eb4b08f9180670b4ca9","amount":"0","gasPrice":"1000000000","gasLimit":"9000","code":"scilla_version 0import ListUtils IntUtils BoolUtils(***************************************************)(* Associated library *)(***************************************************)library WalletLib(* Event emitted when the contract is initialized *)let mk_contract_initialized_event = { _eventname : \"Contract initialized\" }(* Event for communicating a new transaction id *)let mk_transaction_added_event = fun (tc : Uint32) => fun (recipient : ByStr20) => fun (amount : Uint128) => fun (tag : String) => { _eventname : \"Transaction created\" ; transactionId : tc; recipient : recipient; amount : amount; tag : tag }(* Event for communicating the execution of a transaction *)let mk_transaction_executed_event = fun (tc : Uint32) => fun (recipient : ByStr20) => fun (amount : Uint128) => fun (tag : String) => { _eventname : \"Transaction executed\"; transactionId : tc; recipient : recipient; amount : amount; tag : tag }(* Event for communicating that a transaction was signed *)let mk_signed_transaction_event = fun (tc : Uint32) => { _eventname : \"Transaction signed\"; transactionId : tc }(* Event for communicating that a signature was revoked *)let mk_signature_revoked_event = fun (tc : Uint32) => { _eventname : \"Signature revoked\"; transactionId : tc }type Error =| NonOwnerCannotSign| UnknownTransactionId| InsufficientFunds| NoSignatureListFound| AlreadySigned| NotAlreadySigned| InvalidContract| InvalidAmount| NotEnoughSignatures| SenderMayNotExecute| NonOwnerCannotSubmit| IncorrectSignatureCount(* Error events *)let mk_error_event = fun (err : Error) => let err_code = match err with | NonOwnerCannotSign => Int32 -1 | UnknownTransactionId => Int32 -2 | InsufficientFunds => Int32 -3 | NoSignatureListFound => Int32 -4 | AlreadySigned => Int32 -5 | NotAlreadySigned => Int32 -6 | InvalidContract => Int32 -7 | InvalidAmount => Int32 -8 | NotEnoughSignatures => Int32 -9 | SenderMayNotExecute => Int32 -10 | NonOwnerCannotSubmit => Int32 -11 | IncorrectSignatureCount => Int32 -12 end in { _eventname : \"WalletError\" ; err_code : err_code }let t = Truelet f = Falselet zero = Uint32 0let one = Uint32 1let transaction_inc = one(* One (potential) transaction, consisting of a recipient address, an amount, *)(* and a tag (in case the recipient is another contract *)type Transaction =| Trans of ByStr20 Uint128 String(* Make map of owners *)let mk_owners_map = fun (owners : List ByStr20) => let init = Emp ByStr20 Bool in let iter = fun (acc : Map ByStr20 Bool) => fun (cur_owner : ByStr20) => (* Add owner unconditionally. We check for duplicates later *) builtin put acc cur_owner t in let folder = @list_foldl ByStr20 (Map ByStr20 Bool) in folder iter init owners(* Check that the number of distinct owners is greater than 0 *)let check_validity_and_build_owners_map = fun (owners : List ByStr20) => fun (required_signatures : Uint32) => let len = @list_length ByStr20 in let no_of_owners = len owners in let owners_ok = builtin lt zero no_of_owners in let required_sigs_not_too_low = builtin lt zero required_signatures in let required_sigs_too_high = builtin lt no_of_owners required_signatures in let required_sigs_not_too_high = negb required_sigs_too_high in let required_sigs_ok = andb required_sigs_not_too_high required_sigs_not_too_low in let all_ok = andb required_sigs_ok owners_ok in match all_ok with | True => let owners_map = mk_owners_map owners in let size_of_owners_map = builtin size owners_map in let equal_size = builtin eq size_of_owners_map no_of_owners in match equal_size with | True => (* No duplicates *) Some {Map ByStr20 Bool} owners_map | False => (* Duplicate owners found *) None {Map ByStr20 Bool} end | False => None {Map ByStr20 Bool} end(* Create one transaction message *)let transaction_msg = fun (recipient : ByStr20) => fun (amount : Uint128) => fun (tag : String) => {_tag : tag; _recipient : recipient; _amount : amount }(* Wrap one transaction message as singleton list *)let transaction_msg_as_list = fun (recipient : ByStr20) => fun (amount : Uint128) => fun (tag : String) => let one_msg = fun (msg : Message) => let nil_msg = Nil {Message} in Cons {Message} msg nil_msg in let msg = transaction_msg recipient amount tag in one_msg msgtype ContractValidity =| Valid| Invalid| Uncheckedlet valid = Validlet invalid = Invalid(***************************************************)(* The contract definition *)(* *)(* This contract holds funds that can be paid out *)(* to arbitrary users, provided that enough people *)(* in the collection of owners sign off on the *)(* payout. *)(* *)(* Before transactions can be submitted or signed *)(* for, the contract must be initialized. This is *)(* done by invoking the AddFunds transition. This *)(* transition initializes the contract fields - *)(* if the fields have not been initialized, all *)(* other transitions will fail whenever they are *)(* invoked. *)(* *)(* The transaction must be added to the contract *)(* before signatures can be collected. Once enough *)(* signatures are collected, the recipient can ask *)(* for the transaction to be executed and the *)(* money paid out. *)(* *)(* If an owner changes his mind about a *)(* transaction, the signature can be revoked until *)(* the transaction is executed. *)(* *)(* This wallet does not allow adding or removing *)(* owners, or changing the number of required *)(* signatures. To do any of those things, perform *)(* the following steps: *)(* *)(* 1. Deploy a new wallet with owners and *)(* required_signatures set to the new values. *)(* MAKE SURE THAT THE NEW WALLET HAS BEEN *)(* SUCCESFULLY DEPLOYED WITH THE CORRECT *)(* PARAMETERS BEFORE CONTINUING! *)(* 2. Invoke the SubmitTransaction transition on *)(* the old wallet with the following *)(* parameters: *)(* recipient : The address of the new wallet *)(* amount : The _balance of the old wallet *)(* tag : \"AddFunds\" *)(* 3. Have (a sufficient number of) the owners of *)(* the old contract invoke the SignTransaction *)(* transition on the old wallet. The parameter *)(* transactionId should be set to the Id of the *)(* transaction created in step 2. *)(* 4. Have one of the owners of the old contract *)(* invoke the ExecuteTransaction transition on *)(* the old contract. This will cause the entire *)(* balance of the old contract to be *)(* transferred to the new wallet. Note that no *)(* un-executed transactions will be transferred *)(* to the new wallet along with the funds. *)(* *)(* WARNING: If a sufficient number of owners lose *)(* their private keys, or for any other reason are *)(* unable or unwilling to sign for new *)(* transactions, the funds in the wallet will be *)(* locked forever. It is therefore a good idea to *)(* set required_signatures to a value strictly *)(* less than the number of owners, so that the *)(* remaining owners can retrieve the funds should *)(* such a scenario occur. *)(* *)(* If an owner loses his private key, the *)(* remaining owners should move the funds to a new *)(* wallet (using the workflow described above) to *)(* ensure that funds are not locked if another *)(* owner loses his private key. The owner who *)(* originally lost his private key can generate a *)(* new key, and the corresponding address be added *)(* to the new wallet, so that the same set of *)(* persons own the new wallet. *)(* *)(***************************************************)contract Wallet(owners_list : List ByStr20,required_signatures : Uint32)(* Funds are not allowed to be added if the contract is not valid *)field contract_valid : ContractValidity = Unchecked(* adr -> True indicates an owner *)(* adr not in map indicates non-owner *)(* adr -> False is not used *)(* The initial owners will be added as owners when funds are *)(* initially added to the contract. *)field owners : Map ByStr20 Bool = Emp ByStr20 Boolfield transactionCount : Uint32 = Uint32 0(* Collected signatures for transactions *)field signatures : Map Uint32 (Map ByStr20 Bool) = Emp Uint32 (Map ByStr20 Bool)(* Running count of collected signatures for transactions *)field signature_counts : Map Uint32 Uint32 = Emp Uint32 Uint32(* Transactions *)field transactions : Map Uint32 Transaction = Emp Uint32 Transactionprocedure MakeError (err : Error) e = mk_error_event err; event eend(* Add signature to signature list *)procedure AddSignature (transactionId : Uint32, signee : ByStr20) sig <- exists signatures[transactionId][signee]; match sig with | False => count <- signature_counts[transactionId]; match count with | None => (* 0 signatures *) signature_counts[transactionId] := one | Some c => new_c = builtin add c one; signature_counts[transactionId] := new_c end; signatures[transactionId][signee] := t; e = mk_signed_transaction_event transactionId; event e | True => (* Already signed *) err = AlreadySigned; MakeError err endend(* Submit a transaction for future signoff *)transition SubmitTransaction (recipient : ByStr20, amount : Uint128, tag : String) (* Only allow owners to submit new transactions *) sender_is_owner <- exists owners[_sender]; match sender_is_owner with | False => err = NonOwnerCannotSubmit; MakeError err | True => tc <- transactionCount; zero = Uint128 0; amount_is_zero = builtin eq amount zero; match amount_is_zero with | True => (* Illegal transaction *) err = InvalidAmount; MakeError err | False => (* Create new transaction *) transaction = Trans recipient amount tag; (* Add transaction to outstanding list of transactions *) transactions[tc] := transaction; (* Sender implicitly signs *) AddSignature tc _sender; (* Increment transaction counter *) tc_new = builtin add tc transaction_inc; (* Update transaction count *) transactionCount := tc_new; (* Create event with transaction Id *) e = mk_transaction_added_event tc recipient amount tag; event e end endend(* Sign off on an existing transaction *)transition SignTransaction (transactionId : Uint32) (* Only the owner is allowed to sign off transactions *) sender_is_owner <- exists owners[_sender]; match sender_is_owner with | False => err = NonOwnerCannotSign; MakeError err | True => (* Transaction must have been submitted *) transaction <- transactions[transactionId]; match transaction with | None => err = UnknownTransactionId; MakeError err | Some _ => (* Remaining error cases handled by AddSignature *) AddSignature transactionId _sender end endend(* Delete transaction and signatures *)procedure DeleteTransaction (transactionId : Uint32) delete transactions[transactionId]; delete signatures[transactionId]; delete signature_counts[transactionId]end(* Execute signed-off transaction *)transition ExecuteTransaction (transactionId : Uint32) transaction_opt <- transactions[transactionId]; match transaction_opt with | None => (* Transaction was not found. *) err = UnknownTransactionId; MakeError err | Some (Trans recipient amount tag) => (* Only the recipient or an owner can execute the transaction *) recipient_is_sender = builtin eq recipient _sender; sender_is_owner <- exists owners[_sender]; sender_may_execute = orb recipient_is_sender sender_is_owner; match sender_may_execute with | False => err = SenderMayNotExecute; MakeError err | True => (* Check for sufficient funds *) bal <- _balance; not_enough_money = builtin lt bal amount; match not_enough_money with | True => err = InsufficientFunds; MakeError err | False => sig_count_opt <- signature_counts[transactionId]; match sig_count_opt with | None => (* Signature count not found, even though the transaction exists.*) err = NoSignatureListFound; MakeError err | Some sig_count => not_enough_signatures = builtin lt sig_count required_signatures; match not_enough_signatures with | True => err = NotEnoughSignatures; MakeError err | False => (* Transaction approved, and enough money available. *) (* Remove transaction and signatures, and execute. *) DeleteTransaction transactionId; msgs = transaction_msg_as_list recipient amount tag; send msgs; e = mk_transaction_executed_event transactionId recipient amount tag; event e end end end end endend(* Revoke signature of existing transaction, if it has not yet been executed. *)transition RevokeSignature (transactionId : Uint32) sig <- exists signatures[transactionId][_sender]; match sig with | False => err = NotAlreadySigned; MakeError err | True => count <- signature_counts[transactionId]; match count with | None => err = IncorrectSignatureCount; MakeError err | Some c => c_is_zero = builtin eq c zero; match c_is_zero with | True => err = IncorrectSignatureCount; MakeError err | False => new_c = builtin sub c one; signature_counts[transactionId] := new_c; delete signatures[transactionId][_sender]; e = mk_signature_revoked_event transactionId; event e end end endend(* Add funds to wallet *)transition AddFunds () (* Check validity of contract. If the contract is invalid, funds will not be accepted. *) validity <- contract_valid; match validity with | Unchecked => (* Check validity and build owners map *) owners_map_opt = check_validity_and_build_owners_map owners_list required_signatures; match owners_map_opt with | Some owners_map => contract_valid := valid; owners := owners_map; e = mk_contract_initialized_event; event e | None => contract_valid := invalid end | Valid => (* Already checked *) | Invalid => (* Already checked *) end;(* Read validity field again, as it may have been updated. *)(* Only accept funds if the contract is valid. *) validity <- contract_valid; match validity with | Unchecked => (* This should not happen *) err = InvalidContract; MakeError err | Invalid => err = InvalidContract; MakeError err | Valid => accept endend","data":"[{\"vname\":\"_scilla_version\",\"type\":\"Uint32\",\"value\":\"0\"},{\"vname\":\"initial_owners\",\"type\":\"List ByStr20\",\"value\":{\"constructor\":\"Cons\",\"argtypes\":[\"ByStr20\"],\"arguments\":[\"0x1234567890123456789012345678906784567890\",{\"constructor\":\"Cons\",\"argtypes\":[\"ByStr20\"],\"arguments\":[\"0xabcdeabcde123456786782345678901234567890\",{\"constructor\":\"Cons\",\"argtypes\":[\"ByStr20\"],\"arguments\":[\"0xffcdeabcde126786789012345678901234567890\",{\"constructor\":\"Nil\",\"argtypes\":[\"ByStr20\"],\"arguments\":[]}]}]}]}},{\"vname\":\"required_signatures\",\"type\":\"Uint32\",\"value\":\"2\"}]","signature":"1c82cb5c08003c52ed128c45a95545be682ec1c0721b6d57a325b33afca2337734c0a4946fef9be9f02aeb9c0ebdc9d533aec1431197857ec30b7f902be84374","priority":false,"pubKey":"031c94966225bf2342e799b0078a4381cbd8c1ce2cd99166106af150e7a300a7a8"}