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
//! Secret Network specific utilities and contracts that
//! are commonly used when developing smart contracts for it.
//! *Feature flag: `scrt`*

#[cfg(feature = "permit")]
pub mod permit;
#[cfg(feature = "vk")]
pub mod vk;
#[cfg(feature = "snip20")]
pub mod snip20;

use crate::cosmwasm_std::{StdResult, CosmosMsg, WasmMsg, Response, to_binary};

/// Default Secret Network message padding size.
pub const BLOCK_SIZE: usize = 256;

pub trait ResponseExt {
    /// Pads the message data to a multiple of [`BLOCK_SIZE`] if it is set.
    fn pad(self) -> Self;
}

/// Creates a new [`WasmMsg::Execute`] using the provided `msg`
/// and padding it to [`BLOCK_SIZE`].
pub fn to_cosmos_msg (
    contract_addr: String,
    code_hash: String,
    msg: &impl serde::Serialize,
) -> StdResult<CosmosMsg> {
    let mut msg = to_binary(msg)?;
    space_pad(&mut msg.0, BLOCK_SIZE);

    Ok(WasmMsg::Execute {
        msg,
        contract_addr,
        code_hash,
        funds: vec![]
    }.into())
}

/// Take a `Vec<u8>` and pad it up to a multiple of `block_size`
/// using spaces at the end.
pub fn space_pad (
    message: &mut Vec<u8>,
    block_size: usize
) -> &mut Vec<u8> {
    let len = message.len();
    let surplus = len % block_size;

    if surplus == 0 {
        return message;
    }

    let missing = block_size - surplus;
    message.reserve(missing);
    message.extend(std::iter::repeat(b' ').take(missing));

    message
}

impl ResponseExt for Response {
    fn pad(mut self) -> Self {
        if let Some(data) = self.data.as_mut() {
            space_pad(&mut data.0, BLOCK_SIZE);
        }

        self
    }
}