Source file fees_storage.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
type error += Cannot_pay_storage_fee
type error += Operation_quota_exceeded
type error += Storage_limit_too_high
let () =
let open Data_encoding in
register_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:(fun ppf () -> Format.fprintf ppf "Cannot pay storage storage fee")
Data_encoding.empty
(function Cannot_pay_storage_fee -> Some () | _ -> None)
(fun () -> Cannot_pay_storage_fee) ;
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
(function Operation_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
(function Storage_limit_too_high -> Some () | _ -> None)
(fun () -> Storage_limit_too_high)
let origination_burn c =
let origination_size = Constants_storage.origination_size c in
let cost_per_byte = Constants_storage.cost_per_byte c in
Tez_repr.(cost_per_byte *? Int64.of_int origination_size)
>|? fun to_be_paid ->
(Raw_context.update_allocated_contracts_count c, to_be_paid)
let start_counting_storage_fees c = Raw_context.init_storage_space_to_pay c
let record_paid_storage_space c contract =
Contract_storage.used_storage_space c contract
>>=? fun size ->
Contract_storage.set_paid_storage_space_and_return_fees_to_pay
c
contract
size
>>=? fun (to_be_paid, c) ->
let c = Raw_context.update_storage_space_to_pay c to_be_paid in
let cost_per_byte = Constants_storage.cost_per_byte c in
Lwt.return
( Tez_repr.(cost_per_byte *? Z.to_int64 to_be_paid)
>|? fun to_burn -> (c, size, to_be_paid, to_burn) )
let record_paid_storage_space_subsidy c contract =
let c = start_counting_storage_fees c in
record_paid_storage_space c contract
>>=? fun (c, size, to_be_paid, _) ->
let (c, _, _) = Raw_context.clear_storage_space_to_pay c in
return (c, size, to_be_paid)
let burn_storage_fees c ~storage_limit ~payer =
let origination_size = Constants_storage.origination_size c in
let (c, storage_space_to_pay, allocated_contracts) =
Raw_context.clear_storage_space_to_pay c
in
let storage_space_for_allocated_contracts =
Z.mul (Z.of_int allocated_contracts) (Z.of_int origination_size)
in
let consumed =
Z.add storage_space_to_pay storage_space_for_allocated_contracts
in
let remaining = Z.sub storage_limit consumed in
if Compare.Z.(remaining < Z.zero) then fail Operation_quota_exceeded
else
let cost_per_byte = Constants_storage.cost_per_byte c in
Tez_repr.(cost_per_byte *? Z.to_int64 consumed)
>>?= fun to_burn ->
if Tez_repr.(to_burn = Tez_repr.zero) then
return c
else
trace
Cannot_pay_storage_fee
( Contract_storage.must_exist c payer
>>=? fun () -> Contract_storage.spend c payer to_burn )
let check_storage_limit c ~storage_limit =
if
Compare.Z.(
storage_limit
> (Raw_context.constants c).hard_storage_limit_per_operation)
|| Compare.Z.(storage_limit < Z.zero)
then error Storage_limit_too_high
else ok_unit