1
1
use cosmwasm_std:: {
2
- coin , entry_point, to_json_binary, BankMsg , Decimal , Deps , DepsMut , DistributionMsg , Env ,
3
- MessageInfo , QuerierWrapper , QueryResponse , Response , StakingMsg , StdError , StdResult , Uint128 ,
4
- WasmMsg ,
2
+ entry_point, to_json_binary, BankMsg , Coin , Decimal , Decimal256 , Deps , DepsMut ,
3
+ DistributionMsg , Env , MessageInfo , QuerierWrapper , QueryResponse , Response , StakingMsg ,
4
+ StdError , StdResult , Uint128 , Uint256 , WasmMsg ,
5
5
} ;
6
6
7
7
use crate :: errors:: { StakingError , Unauthorized } ;
@@ -85,14 +85,16 @@ pub fn transfer(
85
85
let rcpt_raw = deps. api . addr_canonicalize ( & recipient) ?;
86
86
let sender_raw = deps. api . addr_canonicalize ( info. sender . as_str ( ) ) ?;
87
87
88
- let balance = may_load_map ( deps. storage , PREFIX_BALANCE , & sender_raw) ?. unwrap_or_default ( ) ;
88
+ let balance: Uint128 =
89
+ may_load_map ( deps. storage , PREFIX_BALANCE , & sender_raw) ?. unwrap_or_default ( ) ;
89
90
save_map (
90
91
deps. storage ,
91
92
PREFIX_BALANCE ,
92
93
& sender_raw,
93
94
balance. checked_sub ( send) ?,
94
95
) ?;
95
- let balance = may_load_map ( deps. storage , PREFIX_BALANCE , & rcpt_raw) ?. unwrap_or_default ( ) ;
96
+ let balance: Uint128 =
97
+ may_load_map ( deps. storage , PREFIX_BALANCE , & rcpt_raw) ?. unwrap_or_default ( ) ;
96
98
save_map ( deps. storage , PREFIX_BALANCE , & rcpt_raw, balance + send) ?;
97
99
98
100
let res = Response :: new ( )
@@ -105,13 +107,13 @@ pub fn transfer(
105
107
106
108
// get_bonded returns the total amount of delegations from contract
107
109
// it ensures they are all the same denom
108
- fn get_bonded ( querier : & QuerierWrapper , contract_addr : impl Into < String > ) -> StdResult < Uint128 > {
110
+ fn get_bonded ( querier : & QuerierWrapper , contract_addr : impl Into < String > ) -> StdResult < Uint256 > {
109
111
let bonds = querier. query_all_delegations ( contract_addr) ?;
110
112
if bonds. is_empty ( ) {
111
- return Ok ( Uint128 :: new ( 0 ) ) ;
113
+ return Ok ( Uint256 :: zero ( ) ) ;
112
114
}
113
115
let denom = bonds[ 0 ] . amount . denom . as_str ( ) ;
114
- bonds. iter ( ) . try_fold ( Uint128 :: zero ( ) , |acc, d| {
116
+ bonds. iter ( ) . try_fold ( Uint256 :: zero ( ) , |acc, d| {
115
117
if d. amount . denom . as_str ( ) != denom {
116
118
Err ( StdError :: generic_err ( format ! (
117
119
"different denoms in bonds: '{}' vs '{}'" ,
@@ -123,7 +125,7 @@ fn get_bonded(querier: &QuerierWrapper, contract_addr: impl Into<String>) -> Std
123
125
} )
124
126
}
125
127
126
- fn assert_bonds ( supply : & Supply , bonded : Uint128 ) -> StdResult < ( ) > {
128
+ fn assert_bonds ( supply : & Supply , bonded : Uint256 ) -> StdResult < ( ) > {
127
129
if supply. bonded != bonded {
128
130
Err ( StdError :: generic_err ( format ! (
129
131
"Stored bonded {}, but query bonded: {}" ,
@@ -153,17 +155,19 @@ pub fn bond(deps: DepsMut, env: Env, info: MessageInfo) -> StdResult<Response> {
153
155
let mut supply: Supply = load_item ( deps. storage , KEY_TOTAL_SUPPLY ) ?;
154
156
// TODO: this is just temporary check - we should use dynamic query or have a way to recover
155
157
assert_bonds ( & supply, bonded) ?;
158
+ // note that the conversion to Uint128 limits payment amounts to `u128::MAX`
156
159
let to_mint = if supply. issued . is_zero ( ) || bonded. is_zero ( ) {
157
- payment. amount . mul_floor ( FALLBACK_RATIO )
160
+ Uint128 :: try_from ( payment. amount . mul_floor ( FALLBACK_RATIO ) ) ?
158
161
} else {
159
- payment. amount . multiply_ratio ( supply. issued , bonded)
162
+ Uint128 :: try_from ( payment. amount . multiply_ratio ( supply. issued , bonded) ) ?
160
163
} ;
161
164
supply. bonded = bonded + payment. amount ;
162
165
supply. issued += to_mint;
163
166
save_item ( deps. storage , KEY_TOTAL_SUPPLY , & supply) ?;
164
167
165
168
// update the balance of the sender
166
- let balance = may_load_map ( deps. storage , PREFIX_BALANCE , & sender_raw) ?. unwrap_or_default ( ) ;
169
+ let balance: Uint128 =
170
+ may_load_map ( deps. storage , PREFIX_BALANCE , & sender_raw) ?. unwrap_or_default ( ) ;
167
171
save_map ( deps. storage , PREFIX_BALANCE , & sender_raw, balance + to_mint) ?;
168
172
169
173
// bond them to the validator
@@ -196,7 +200,8 @@ pub fn unbond(deps: DepsMut, env: Env, info: MessageInfo, amount: Uint128) -> St
196
200
let tax = amount. mul_floor ( invest. exit_tax ) ;
197
201
198
202
// deduct all from the account
199
- let balance = may_load_map ( deps. storage , PREFIX_BALANCE , & sender_raw) ?. unwrap_or_default ( ) ;
203
+ let balance: Uint128 =
204
+ may_load_map ( deps. storage , PREFIX_BALANCE , & sender_raw) ?. unwrap_or_default ( ) ;
200
205
save_map (
201
206
deps. storage ,
202
207
PREFIX_BALANCE ,
@@ -205,7 +210,8 @@ pub fn unbond(deps: DepsMut, env: Env, info: MessageInfo, amount: Uint128) -> St
205
210
) ?;
206
211
if tax > Uint128 :: new ( 0 ) {
207
212
// add tax to the owner
208
- let balance = may_load_map ( deps. storage , PREFIX_BALANCE , & owner_raw) ?. unwrap_or_default ( ) ;
213
+ let balance: Uint128 =
214
+ may_load_map ( deps. storage , PREFIX_BALANCE , & owner_raw) ?. unwrap_or_default ( ) ;
209
215
save_map ( deps. storage , PREFIX_BALANCE , & owner_raw, balance + tax) ?;
210
216
}
211
217
@@ -218,14 +224,15 @@ pub fn unbond(deps: DepsMut, env: Env, info: MessageInfo, amount: Uint128) -> St
218
224
let mut supply: Supply = load_item ( deps. storage , KEY_TOTAL_SUPPLY ) ?;
219
225
// TODO: this is just temporary check - we should use dynamic query or have a way to recover
220
226
assert_bonds ( & supply, bonded) ?;
221
- let unbond = remainder. multiply_ratio ( bonded, supply. issued ) ;
227
+ let unbond = Uint256 :: from ( remainder) . multiply_ratio ( bonded, supply. issued ) ;
222
228
supply. bonded = bonded. checked_sub ( unbond) ?;
223
229
supply. issued = supply. issued . checked_sub ( remainder) ?;
224
230
supply. claims += unbond;
225
231
save_item ( deps. storage , KEY_TOTAL_SUPPLY , & supply) ?;
226
232
227
233
// add a claim to this user to get their tokens after the unbonding period
228
- let claim = may_load_map ( deps. storage , PREFIX_CLAIMS , & sender_raw) ?. unwrap_or_default ( ) ;
234
+ let claim: Uint256 =
235
+ may_load_map ( deps. storage , PREFIX_CLAIMS , & sender_raw) ?. unwrap_or_default ( ) ;
229
236
save_map ( deps. storage , PREFIX_CLAIMS , & sender_raw, claim + unbond) ?;
230
237
231
238
// unbond them
@@ -236,7 +243,7 @@ pub fn unbond(deps: DepsMut, env: Env, info: MessageInfo, amount: Uint128) -> St
236
243
. add_attribute ( "burnt" , amount)
237
244
. add_message ( StakingMsg :: Undelegate {
238
245
validator : invest. validator ,
239
- amount : coin ( unbond. u128 ( ) , & invest. bond_denom ) ,
246
+ amount : Coin :: new ( unbond, & invest. bond_denom ) ,
240
247
} ) ;
241
248
Ok ( res)
242
249
}
@@ -247,7 +254,7 @@ pub fn claim(deps: DepsMut, env: Env, info: MessageInfo) -> StdResult<Response>
247
254
let mut balance = deps
248
255
. querier
249
256
. query_balance ( env. contract . address , invest. bond_denom ) ?;
250
- if balance. amount < invest. min_withdrawal {
257
+ if balance. amount < invest. min_withdrawal . into ( ) {
251
258
return Err ( StdError :: generic_err (
252
259
"Insufficient balance in contract to process claim" ,
253
260
) ) ;
@@ -325,7 +332,7 @@ pub fn _bond_all_tokens(
325
332
let updated = update_item ( deps. storage , KEY_TOTAL_SUPPLY , |mut supply : Supply | {
326
333
balance. amount = balance. amount . checked_sub ( supply. claims ) ?;
327
334
// this just triggers the "no op" case if we don't have min_withdrawal left to reinvest
328
- balance. amount . checked_sub ( invest. min_withdrawal ) ?;
335
+ balance. amount . checked_sub ( invest. min_withdrawal . into ( ) ) ?;
329
336
supply. bonded += balance. amount ;
330
337
Ok ( supply)
331
338
} ) ;
@@ -393,11 +400,14 @@ pub fn query_investment(deps: Deps) -> StdResult<InvestmentResponse> {
393
400
validator : invest. validator ,
394
401
min_withdrawal : invest. min_withdrawal ,
395
402
token_supply : supply. issued ,
396
- staked_tokens : coin ( supply. bonded . u128 ( ) , & invest. bond_denom ) ,
403
+ staked_tokens : Coin :: new ( supply. bonded , invest. bond_denom ) ,
397
404
nominal_value : if supply. issued . is_zero ( ) {
398
405
FALLBACK_RATIO
399
406
} else {
400
- Decimal :: from_ratio ( supply. bonded , supply. issued )
407
+ // TODO: use Decimal256???
408
+ Decimal256 :: from_ratio ( supply. bonded , supply. issued )
409
+ . try_into ( )
410
+ . map_err ( |_| StdError :: generic_err ( "nominal value too high" ) ) ?
401
411
} ,
402
412
} ;
403
413
Ok ( res)
@@ -409,7 +419,7 @@ mod tests {
409
419
use cosmwasm_std:: testing:: {
410
420
message_info, mock_dependencies, mock_env, MockQuerier , StakingQuerier , MOCK_CONTRACT_ADDR ,
411
421
} ;
412
- use cosmwasm_std:: { coins, Addr , Coin , CosmosMsg , Decimal , FullDelegation , Validator } ;
422
+ use cosmwasm_std:: { coin , coins, Addr , Coin , CosmosMsg , Decimal , FullDelegation , Validator } ;
413
423
use std:: str:: FromStr ;
414
424
415
425
fn sample_validator ( addr : & str ) -> Validator {
0 commit comments