123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)typeerror+=Cannot_pay_storage_fee(* `Temporary *)typeerror+=Negative_storage_input(* `Temporary *)typeerror+=Operation_quota_exceeded(* `Temporary *)typeerror+=Storage_limit_too_high(* `Permanent *)let()=letopenData_encodinginregister_error_kind`Temporary~id:"contract.cannot_pay_storage_fee"~title:"Cannot pay storage fee"~description:"The storage fee is higher than the contract balance"~pp:(funppf()->Format.fprintfppf"Cannot pay storage fee")Data_encoding.empty(functionCannot_pay_storage_fee->Some()|_->None)(fun()->Cannot_pay_storage_fee);register_error_kind`Temporary~id:"contract.negative_storage_input"~title:"Negative storage input"~description:"The storage amount asked for an operation is null or negative"~pp:(funppf()->Format.fprintfppf"Null or negative storage input")Data_encoding.empty(functionNegative_storage_input->Some()|_->None)(fun()->Negative_storage_input);register_error_kind`Temporary~id:"storage_exhausted.operation"~title:"Storage quota exceeded for the operation"~description:"A script or one of its callee wrote more bytes than the operation said \
it would"Data_encoding.empty(functionOperation_quota_exceeded->Some()|_->None)(fun()->Operation_quota_exceeded);register_error_kind`Permanent~id:"storage_limit_too_high"~title:"Storage limit out of protocol hard bounds"~description:"A transaction tried to exceed the hard limit on storage"empty(functionStorage_limit_too_high->Some()|_->None)(fun()->Storage_limit_too_high)letrecord_global_constant_storage_spacecontextsize=(* Following the precedent of big_map, a key in the
global table of constants costs 65 bytes (see
[Lazy_storage_diff.Big_map.bytes_size_for_big_map_key])*)letcost_of_key=Z.of_int65inletto_be_paid=Z.addsizecost_of_keyin(context,to_be_paid)letrecord_paid_storage_spacectxtcontract_hash=letopenLwt_result_syntaxinletcontract=Contract_repr.Originatedcontract_hashin(* Get the new size of the contract's storage. *)let*new_storage_size=Contract_storage.used_storage_spacectxtcontractinlet+to_be_paid,c=Contract_storage.set_paid_storage_space_and_return_fees_to_payctxtcontractnew_storage_sizein(c,new_storage_size,to_be_paid)letsource_must_existcsrc=matchsrcwith|`Contractsrc->Contract_storage.must_existcsrc|_->return_unitletburn_storage_fees?(origin=Receipt_repr.Block_application)c~storage_limit~payerconsumed=letopenLwt_result_syntaxinletremaining=Z.substorage_limitconsumedinifCompare.Z.(remaining<Z.zero)thentzfailOperation_quota_exceededelseletcost_per_byte=Constants_storage.cost_per_bytecinlet*?to_burn=Tez_repr.(cost_per_byte*?Z.to_int64consumed)in(* Burning the fees... *)ifTez_repr.(to_burn=Tez_repr.zero)then(* If the payer was deleted by transferring all its balance, and no space
was used, burning zero would fail *)return(c,remaining,[])elsetraceCannot_pay_storage_fee(let*()=source_must_existcpayerinlet+ctxt,balance_updates=Token.transfer~origincpayer`Storage_feesto_burnin(ctxt,remaining,balance_updates))letburn_storage_increase_fees?(origin=Receipt_repr.Block_application)c~payeramount_in_bytes=letopenLwt_result_syntaxinifCompare.Z.(amount_in_bytes<=Z.zero)thentzfailNegative_storage_inputelseletcost_per_byte=Constants_storage.cost_per_bytecinlet*?to_burn=Tez_repr.(cost_per_byte*?Z.to_int64amount_in_bytes)in(* Burning the fees... *)traceCannot_pay_storage_fee(let*()=source_must_existcpayerinToken.transfer~origincpayer`Storage_feesto_burn)letburn_origination_fees?(origin=Receipt_repr.Block_application)c~storage_limit~payer=letorigination_size=Constants_storage.origination_sizecinburn_storage_fees~originc~storage_limit~payer(Z.of_intorigination_size)letburn_sc_rollup_origination_fees?(origin=Receipt_repr.Block_application)c~storage_limit~payerconsumed=burn_storage_fees~originc~storage_limit~payerconsumedletburn_zk_rollup_origination_fees?(origin=Receipt_repr.Block_application)c~storage_limit~payerconsumed=burn_storage_fees~originc~storage_limit~payerconsumedletcheck_storage_limitc~storage_limit=letopenResult_syntaxinifCompare.Z.(storage_limit>(Raw_context.constantsc).hard_storage_limit_per_operation)||Compare.Z.(storage_limit<Z.zero)thentzfailStorage_limit_too_highelsereturn_unit