1use crate::util::path::resolve_path;
2use crate::util::variable::get_var;
3use crate::ContractError;
4use cosmwasm_std::{
5 to_vec, ContractResult, Decimal256, Deps, Env, StdError, SystemResult, Uint256,
6};
7use cw_storage_plus::KeyDeserialize;
8use json_codec_wasm::ast::Ref;
9use json_codec_wasm::Decoder;
10use warp_resolver_pkg::condition::{
11 BlockExpr, Condition, DecimalFnOp, Expr, GenExpr, IntFnOp, NumEnvValue, NumExprOp,
12 NumExprValue, NumFnValue, NumOp, NumValue, StringOp, TimeExpr, TimeOp, Value,
13};
14use warp_resolver_pkg::variable::{QueryExpr, Variable};
15use std::str::FromStr;
16
17pub fn resolve_cond(
18 deps: Deps,
19 env: Env,
20 cond: Condition,
21 vars: &Vec<Variable>,
22) -> Result<bool, ContractError> {
23 match cond {
24 Condition::And(conds) => {
25 for cond in conds {
26 if !resolve_cond(deps, env.clone(), *cond, vars)? {
27 return Ok(false);
28 }
29 }
30 Ok(true)
31 }
32 Condition::Or(conds) => {
33 for cond in conds {
34 if resolve_cond(deps, env.clone(), *cond, vars)? {
35 return Ok(true);
36 }
37 }
38 Ok(false)
39 }
40 Condition::Not(cond) => Ok(!resolve_cond(deps, env, *cond, vars)?),
41 Condition::Expr(expr) => Ok(resolve_expr(deps, env, *expr, vars)?),
42 }
43}
44
45pub fn resolve_expr(
46 deps: Deps,
47 env: Env,
48 expr: Expr,
49 vars: &Vec<Variable>,
50) -> Result<bool, ContractError> {
51 match expr {
52 Expr::String(expr) => resolve_string_expr(deps, env, expr, vars),
53 Expr::Uint(expr) => resolve_uint_expr(deps, env, expr, vars),
54 Expr::Int(expr) => resolve_int_expr(deps, env, expr, vars),
55 Expr::Decimal(expr) => resolve_decimal_expr(deps, env, expr, vars),
56 Expr::Timestamp(expr) => resolve_timestamp_expr(deps, env, expr),
57 Expr::BlockHeight(expr) => resolve_block_expr(deps, env, expr),
58 Expr::Bool(expr) => resolve_ref_bool(deps, env, expr, vars),
59 }
60}
61
62pub fn resolve_int_expr(
63 deps: Deps,
64 env: Env,
65 expr: GenExpr<NumValue<i128, NumExprOp, IntFnOp>, NumOp>,
66 vars: &Vec<Variable>,
67) -> Result<bool, ContractError> {
68 let left = resolve_num_value_int(deps, env.clone(), expr.left, vars)?;
69 let right = resolve_num_value_int(deps, env.clone(), expr.right, vars)?;
70
71 Ok(resolve_int_op(deps, env, left, right, expr.op))
72}
73
74pub fn resolve_num_value_int(
75 deps: Deps,
76 env: Env,
77 value: NumValue<i128, NumExprOp, IntFnOp>,
78 vars: &Vec<Variable>,
79) -> Result<i128, ContractError> {
80 match value {
81 NumValue::Simple(value) => Ok(value),
82 NumValue::Expr(expr) => resolve_num_expr_int(deps, env, expr, vars),
83 NumValue::Ref(expr) => resolve_ref_int(deps, env, expr, vars),
84 NumValue::Fn(expr) => resolve_num_fn_int(deps, env, expr, vars),
85 NumValue::Env(_expr) => Err(ContractError::ConditionError {
86 msg: "Int resolve Env.".to_string(),
87 }),
88 }
89}
90
91fn resolve_ref_int(
92 _deps: Deps,
93 _env: Env,
94 r: String,
95 vars: &Vec<Variable>,
96) -> Result<i128, ContractError> {
97 let var = get_var(r, vars)?;
98 let res = match var {
99 Variable::Static(s) => {
100 let val = s.clone().value;
101 str::parse::<i128>(&val)?
102 }
103 Variable::Query(q) => {
104 let val = q.clone().value.ok_or(ContractError::ConditionError {
105 msg: format!("Int Query value not found: {}", q.name),
106 })?;
107 str::parse::<i128>(&val)?
108 }
109 Variable::External(e) => {
110 let val = e.clone().value.ok_or(ContractError::ConditionError {
111 msg: format!("Int External value not found: {}", e.name),
112 })?;
113 str::parse::<i128>(&val)?
114 }
115 };
116
117 Ok(res)
118}
119
120fn resolve_num_fn_int(
121 deps: Deps,
122 env: Env,
123 expr: NumFnValue<i128, NumExprOp, IntFnOp>,
124 vars: &Vec<Variable>,
125) -> Result<i128, ContractError> {
126 let right = resolve_num_value_int(deps, env, *expr.right, vars)?;
127
128 match expr.op {
129 IntFnOp::Abs => Ok(right.abs()),
130 IntFnOp::Neg => {
131 Ok(right
132 .checked_mul(i128::from(-1i64))
133 .ok_or(ContractError::ConditionError {
134 msg: "Int negation error.".to_string(),
135 })?)
136 }
137 }
138}
139
140pub fn resolve_num_expr_int(
141 deps: Deps,
142 env: Env,
143 expr: NumExprValue<i128, NumExprOp, IntFnOp>,
144 vars: &Vec<Variable>,
145) -> Result<i128, ContractError> {
146 let left = resolve_num_value_int(deps, env.clone(), *expr.left, vars)?;
147 let right = resolve_num_value_int(deps, env, *expr.right, vars)?;
148
149 match expr.op {
150 NumExprOp::Sub => Ok(left
151 .checked_sub(right)
152 .ok_or(ContractError::ConditionError {
153 msg: "Int checked sub error.".to_string(),
154 })?),
155 NumExprOp::Add => Ok(left
156 .checked_add(right)
157 .ok_or(ContractError::ConditionError {
158 msg: "Int checked add error.".to_string(),
159 })?),
160 NumExprOp::Div => Ok(left
161 .checked_div(right)
162 .ok_or(ContractError::ConditionError {
163 msg: "Int checked div error.".to_string(),
164 })?),
165 NumExprOp::Mul => Ok(left
166 .checked_mul(right)
167 .ok_or(ContractError::ConditionError {
168 msg: "Int checked mul error.".to_string(),
169 })?),
170 NumExprOp::Mod => Ok(left
171 .checked_rem(right)
172 .ok_or(ContractError::ConditionError {
173 msg: "Int checked rem error.".to_string(),
174 })?),
175 }
176}
177
178pub fn resolve_uint_expr(
179 deps: Deps,
180 env: Env,
181 expr: GenExpr<NumValue<Uint256, NumExprOp, IntFnOp>, NumOp>,
182 vars: &Vec<Variable>,
183) -> Result<bool, ContractError> {
184 let left = resolve_num_value_uint(deps, env.clone(), expr.left, vars)?;
185 let right = resolve_num_value_uint(deps, env.clone(), expr.right, vars)?;
186
187 Ok(resolve_uint_op(deps, env, left, right, expr.op))
188}
189
190pub fn resolve_num_value_uint(
191 deps: Deps,
192 env: Env,
193 value: NumValue<Uint256, NumExprOp, IntFnOp>,
194 vars: &Vec<Variable>,
195) -> Result<Uint256, ContractError> {
196 match value {
197 NumValue::Simple(value) => Ok(value),
198 NumValue::Expr(expr) => resolve_num_expr_uint(deps, env, expr, vars),
199 NumValue::Ref(expr) => resolve_ref_uint(deps, env, expr, vars),
200 NumValue::Fn(_) => Err(ContractError::ConditionError {
201 msg: "Uint resolve Fn.".to_string(),
202 }),
203 NumValue::Env(expr) => resolve_num_env_uint(deps, env, expr, vars),
204 }
205}
206
207fn resolve_ref_uint(
208 _deps: Deps,
209 _env: Env,
210 r: String,
211 vars: &Vec<Variable>,
212) -> Result<Uint256, ContractError> {
213 let var = get_var(r, vars)?;
214 let res = match var {
215 Variable::Static(s) => {
216 let val = s.clone().value;
217 Uint256::from_str(&val)?
218 }
219 Variable::Query(q) => {
220 let val = q.clone().value.ok_or(ContractError::ConditionError {
221 msg: format!("Uint Query value not found: {}", q.name),
222 })?;
223 Uint256::from_str(&val)?
224 }
225 Variable::External(e) => {
226 let val = e.clone().value.ok_or(ContractError::ConditionError {
227 msg: format!("Uint External value not found: {}", e.name),
228 })?;
229 Uint256::from_str(&val)?
230 }
231 };
232
233 Ok(res)
234}
235
236pub fn resolve_num_expr_uint(
237 deps: Deps,
238 env: Env,
239 expr: NumExprValue<Uint256, NumExprOp, IntFnOp>,
240 vars: &Vec<Variable>,
241) -> Result<Uint256, ContractError> {
242 let left = resolve_num_value_uint(deps, env.clone(), *expr.left, vars)?;
243 let right = resolve_num_value_uint(deps, env, *expr.right, vars)?;
244
245 match expr.op {
246 NumExprOp::Sub => {
247 Ok(left
248 .checked_sub(right)
249 .map_err(|_| ContractError::ConditionError {
250 msg: "Uint checked sub error.".to_string(),
251 })?)
252 }
253 NumExprOp::Add => {
254 Ok(left
255 .checked_add(right)
256 .map_err(|_| ContractError::ConditionError {
257 msg: "Uint checked add error.".to_string(),
258 })?)
259 }
260 NumExprOp::Div => {
261 Ok(left
262 .checked_div(right)
263 .map_err(|_| ContractError::ConditionError {
264 msg: "Uint checked div error.".to_string(),
265 })?)
266 }
267 NumExprOp::Mul => {
268 Ok(left
269 .checked_mul(right)
270 .map_err(|_| ContractError::ConditionError {
271 msg: "Uint checked mul error.".to_string(),
272 })?)
273 }
274 NumExprOp::Mod => {
275 Ok(left
276 .checked_rem(right)
277 .map_err(|_| ContractError::ConditionError {
278 msg: "Uint checked rem error.".to_string(),
279 })?)
280 }
281 }
282}
283
284pub fn resolve_num_env_uint(
285 _deps: Deps,
286 env: Env,
287 expr: NumEnvValue,
288 _vars: &[Variable],
289) -> Result<Uint256, ContractError> {
290 match expr {
291 NumEnvValue::Time => Ok(env.block.time.seconds().into()),
292 NumEnvValue::BlockHeight => Ok(env.block.height.into()),
293 }
294}
295
296pub fn resolve_decimal_expr(
297 deps: Deps,
298 env: Env,
299 expr: GenExpr<NumValue<Decimal256, NumExprOp, DecimalFnOp>, NumOp>,
300 vars: &Vec<Variable>,
301) -> Result<bool, ContractError> {
302 let left = resolve_num_value_decimal(deps, env.clone(), expr.left, vars)?;
303 let right = resolve_num_value_decimal(deps, env.clone(), expr.right, vars)?;
304
305 Ok(resolve_decimal_op(deps, env, left, right, expr.op))
306}
307
308pub fn resolve_num_value_decimal(
309 deps: Deps,
310 env: Env,
311 value: NumValue<Decimal256, NumExprOp, DecimalFnOp>,
312 vars: &Vec<Variable>,
313) -> Result<Decimal256, ContractError> {
314 match value {
315 NumValue::Simple(value) => Ok(value),
316 NumValue::Expr(expr) => resolve_num_expr_decimal(deps, env, expr, vars),
317 NumValue::Ref(expr) => resolve_ref_decimal(deps, env, expr, vars),
318 NumValue::Fn(expr) => resolve_num_fn_decimal(deps, env, expr, vars),
319 NumValue::Env(_expr) => Err(ContractError::ConditionError {
320 msg: "Decimal resolve Env.".to_string(),
321 }),
322 }
323}
324
325fn resolve_ref_decimal(
326 _deps: Deps,
327 _env: Env,
328 r: String,
329 vars: &Vec<Variable>,
330) -> Result<Decimal256, ContractError> {
331 let var = get_var(r, vars)?;
332 let res = match var {
333 Variable::Static(s) => {
334 let val = s.clone().value;
335 Decimal256::from_str(&val)?
336 }
337 Variable::Query(q) => {
338 let val = q.clone().value.ok_or(ContractError::ConditionError {
339 msg: format!("Decimal Query value not found: {}", q.name),
340 })?;
341 Decimal256::from_str(&val)?
342 }
343 Variable::External(e) => {
344 let val = e.clone().value.ok_or(ContractError::ConditionError {
345 msg: format!("Decimal External value not found: {}", e.name),
346 })?;
347 Decimal256::from_str(&val)?
348 }
349 };
350
351 Ok(res)
352}
353
354fn resolve_num_fn_decimal(
355 deps: Deps,
356 env: Env,
357 expr: NumFnValue<Decimal256, NumExprOp, DecimalFnOp>,
358 vars: &Vec<Variable>,
359) -> Result<Decimal256, ContractError> {
360 let right = resolve_num_value_decimal(deps, env, *expr.right, vars)?;
361
362 match expr.op {
363 DecimalFnOp::Abs => Ok(right.abs_diff(Decimal256::zero())),
364 DecimalFnOp::Neg => {
365 Ok(right.checked_mul(Decimal256::zero().checked_sub(Decimal256::one())?)?)
366 }
367 DecimalFnOp::Floor => Ok(right.floor()),
368 DecimalFnOp::Sqrt => Ok(right.sqrt()),
369 DecimalFnOp::Ceil => Ok(right.ceil()),
370 }
371}
372
373pub fn resolve_num_expr_decimal(
374 deps: Deps,
375 env: Env,
376 expr: NumExprValue<Decimal256, NumExprOp, DecimalFnOp>,
377 vars: &Vec<Variable>,
378) -> Result<Decimal256, ContractError> {
379 let left = resolve_num_value_decimal(deps, env.clone(), *expr.left, vars)?;
380 let right = resolve_num_value_decimal(deps, env, *expr.right, vars)?;
381
382 match expr.op {
383 NumExprOp::Sub => {
384 Ok(left
385 .checked_sub(right)
386 .map_err(|_| ContractError::ConditionError {
387 msg: "Decimal checked sub error.".to_string(),
388 })?)
389 }
390 NumExprOp::Add => {
391 Ok(left
392 .checked_add(right)
393 .map_err(|_| ContractError::ConditionError {
394 msg: "Decimal checked sub error.".to_string(),
395 })?)
396 }
397 NumExprOp::Div => {
398 Ok(left
399 .checked_div(right)
400 .map_err(|_| ContractError::ConditionError {
401 msg: "Decimal checked sub error.".to_string(),
402 })?)
403 }
404 NumExprOp::Mul => {
405 Ok(left
406 .checked_mul(right)
407 .map_err(|_| ContractError::ConditionError {
408 msg: "Decimal checked sub error.".to_string(),
409 })?)
410 }
411 NumExprOp::Mod => {
412 Ok(left
413 .checked_rem(right)
414 .map_err(|_| ContractError::ConditionError {
415 msg: "Decimal checked sub error.".to_string(),
416 })?)
417 }
418 }
419}
420
421pub fn resolve_timestamp_expr(
422 _deps: Deps,
423 env: Env,
424 expr: TimeExpr,
425) -> Result<bool, ContractError> {
426 let res = match expr.op {
427 TimeOp::Lt => env.block.time.seconds().lt(&expr.comparator.u64()),
428 TimeOp::Gt => env.block.time.seconds().gt(&expr.comparator.u64()),
429 };
430
431 Ok(res)
432}
433
434pub fn resolve_block_expr(_deps: Deps, env: Env, expr: BlockExpr) -> Result<bool, ContractError> {
435 let res = match expr.op {
436 NumOp::Eq => env.block.height.eq(&expr.comparator.u64()),
437 NumOp::Neq => env.block.height.ne(&expr.comparator.u64()),
438 NumOp::Lt => env.block.height.lt(&expr.comparator.u64()),
439 NumOp::Gt => env.block.height.gt(&expr.comparator.u64()),
440 NumOp::Gte => env.block.height.ge(&expr.comparator.u64()),
441 NumOp::Lte => env.block.height.le(&expr.comparator.u64()),
442 };
443
444 Ok(res)
445}
446
447pub fn resolve_uint_op(_deps: Deps, _env: Env, left: Uint256, right: Uint256, op: NumOp) -> bool {
448 match op {
449 NumOp::Eq => left.eq(&right),
450 NumOp::Neq => left.ne(&right),
451 NumOp::Lt => left.lt(&right),
452 NumOp::Gt => left.gt(&right),
453 NumOp::Gte => left.ge(&right),
454 NumOp::Lte => left.le(&right),
455 }
456}
457
458pub fn resolve_int_op(_deps: Deps, _env: Env, left: i128, right: i128, op: NumOp) -> bool {
459 match op {
460 NumOp::Eq => left.eq(&right),
461 NumOp::Neq => left.ne(&right),
462 NumOp::Lt => left.lt(&right),
463 NumOp::Gt => left.gt(&right),
464 NumOp::Gte => left.ge(&right),
465 NumOp::Lte => left.le(&right),
466 }
467}
468
469pub fn resolve_decimal_op(
470 _deps: Deps,
471 _env: Env,
472 left: Decimal256,
473 right: Decimal256,
474 op: NumOp,
475) -> bool {
476 match op {
477 NumOp::Eq => left.eq(&right),
478 NumOp::Neq => left.ne(&right),
479 NumOp::Lt => left.lt(&right),
480 NumOp::Gt => left.gt(&right),
481 NumOp::Gte => left.ge(&right),
482 NumOp::Lte => left.le(&right),
483 }
484}
485
486pub fn resolve_string_expr(
487 deps: Deps,
488 env: Env,
489 expr: GenExpr<Value<String>, StringOp>,
490 vars: &Vec<Variable>,
491) -> Result<bool, ContractError> {
492 match (expr.left, expr.right) {
493 (Value::Simple(left), Value::Simple(right)) => {
494 Ok(resolve_str_op(deps, env, left, right, expr.op))
495 }
496 (Value::Simple(left), Value::Ref(right)) => Ok(resolve_str_op(
497 deps,
498 env.clone(),
499 left,
500 resolve_ref_string(deps, env, right, vars)?,
501 expr.op,
502 )),
503 (Value::Ref(left), Value::Simple(right)) => Ok(resolve_str_op(
504 deps,
505 env.clone(),
506 resolve_ref_string(deps, env, left, vars)?,
507 right,
508 expr.op,
509 )),
510 (Value::Ref(left), Value::Ref(right)) => Ok(resolve_str_op(
511 deps,
512 env.clone(),
513 resolve_ref_string(deps, env.clone(), left, vars)?,
514 resolve_ref_string(deps, env, right, vars)?,
515 expr.op,
516 )),
517 }
518}
519
520fn resolve_ref_string(
521 _deps: Deps,
522 _env: Env,
523 r: String,
524 vars: &Vec<Variable>,
525) -> Result<String, ContractError> {
526 let var = get_var(r, vars)?;
527 let res = match var {
528 Variable::Static(s) => s.value.clone(),
529 Variable::Query(q) => q.value.clone().ok_or(ContractError::ConditionError {
530 msg: format!("String Query value not found: {}", q.name),
531 })?,
532 Variable::External(e) => e.value.clone().ok_or(ContractError::ConditionError {
533 msg: format!("String External value not found: {}", e.name),
534 })?,
535 };
536
537 Ok(res)
538}
539
540pub fn resolve_str_op(_deps: Deps, _env: Env, left: String, right: String, op: StringOp) -> bool {
541 match op {
542 StringOp::StartsWith => left.starts_with(&right),
543 StringOp::EndsWith => left.ends_with(&right),
544 StringOp::Contains => left.contains(&right),
545 StringOp::Eq => left.eq(&right),
546 StringOp::Neq => left.ne(&right),
547 }
548}
549
550pub fn resolve_query_expr(deps: Deps, _env: Env, expr: QueryExpr) -> Result<String, ContractError> {
551 let raw = to_vec(&expr.query).map_err(|serialize_err| {
552 StdError::generic_err(format!("Serializing QueryRequest: {}", serialize_err))
553 })?;
554
555 let query_result_binary = match deps.querier.raw_query(&raw) {
556 SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
557 "Querier system error: {}",
558 system_err
559 ))),
560 SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(format!(
561 "Querier contract error: {}",
562 contract_err
563 ))),
564 SystemResult::Ok(ContractResult::Ok(value)) => Ok(value),
565 }?;
566
567 let query_result_str = String::from_vec(base64::decode(query_result_binary.to_string())?)?;
568
569 Ok(query_result_str)
570}
571
572pub fn resolve_query_expr_bool(
573 deps: Deps,
574 env: Env,
575 expr: QueryExpr,
576) -> Result<bool, ContractError> {
577 let query_result_str = resolve_query_expr(deps, env, expr.clone())?;
578 let value = Decoder::default(query_result_str.chars()).decode()?;
579 let r = Ref::new(&value);
580 let resolved = resolve_path(r, expr.selector)?;
581
582 resolved.bool().ok_or(ContractError::DecodeError {})
583}
584
585pub fn resolve_ref_bool(
586 _deps: Deps,
587 _env: Env,
588 r: String,
589 vars: &Vec<Variable>,
590) -> Result<bool, ContractError> {
591 let var = get_var(r, vars)?;
592 let res = match var {
593 Variable::Static(s) => {
594 let val = s.clone().value;
595 str::parse::<bool>(&val)?
596 }
597 Variable::Query(q) => {
598 let val = q.clone().value.ok_or(ContractError::ConditionError {
599 msg: format!("Bool Query value not found: {}", q.name),
600 })?;
601 str::parse::<bool>(&val)?
602 }
603 Variable::External(e) => {
604 let val = e.clone().value.ok_or(ContractError::ConditionError {
605 msg: format!("Bool External value not found: {}", e.name),
606 })?;
607 str::parse::<bool>(&val)?
608 }
609 };
610 Ok(res)
611}
612
613pub fn resolve_query_expr_uint(
614 deps: Deps,
615 env: Env,
616 expr: QueryExpr,
617) -> Result<Uint256, ContractError> {
618 let query_result_str = resolve_query_expr(deps, env, expr.clone())?;
619 let value = Decoder::default(query_result_str.chars()).decode()?;
620 let r = Ref::new(&value);
621 let resolved = resolve_path(r, expr.selector)?;
622
623 let str_result = Uint256::from_str(resolved.string().ok_or(ContractError::DecodeError {})?);
624
625 let val = match str_result {
626 Ok(result) => result,
627 Err(_) => Uint256::from(resolved.u128().ok_or(ContractError::DecodeError {})?),
628 };
629
630 Ok(val)
631}
632
633pub fn resolve_query_expr_int(
634 deps: Deps,
635 env: Env,
636 expr: QueryExpr,
637) -> Result<i128, ContractError> {
638 let query_result_str = resolve_query_expr(deps, env, expr.clone())?;
639 let value = Decoder::default(query_result_str.chars()).decode()?;
640 let r = Ref::new(&value);
641 let resolved = resolve_path(r, expr.selector)?;
642
643 resolved.i128().ok_or(ContractError::DecodeError {})
644}
645
646pub fn resolve_query_expr_decimal(
647 deps: Deps,
648 env: Env,
649 expr: QueryExpr,
650) -> Result<Decimal256, ContractError> {
651 let query_result_str = resolve_query_expr(deps, env, expr.clone())?;
652 let value = Decoder::default(query_result_str.chars()).decode()?;
653 let r = Ref::new(&value);
654 let resolved = resolve_path(r, expr.selector)?;
655
656 Ok(Decimal256::from_str(
657 resolved.string().ok_or(ContractError::DecodeError {})?,
658 )?)
659}
660
661pub fn resolve_query_expr_string(
662 deps: Deps,
663 env: Env,
664 expr: QueryExpr,
665) -> Result<String, ContractError> {
666 let query_result_str = resolve_query_expr(deps, env, expr.clone())?;
667 let value = Decoder::default(query_result_str.chars()).decode()?;
668 let r = Ref::new(&value);
669 let resolved = resolve_path(r, expr.selector)?;
670
671 Ok(resolved
672 .string()
673 .ok_or(ContractError::DecodeError {})?
674 .to_string())
675}