Skip to content

Commit

Permalink
wallet added
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzious committed Oct 30, 2023
1 parent 1af2239 commit 8dfbb1e
Show file tree
Hide file tree
Showing 10 changed files with 442 additions and 1 deletion.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[workspace]
members = [
"contracts/limit",
"contracts/entrypoint"
"contracts/entrypoint",
"contracts/scw"
]

# [workspace.package]
Expand All @@ -13,6 +14,7 @@ members = [
optimize = """docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/workspace-optimizer:0.12.10
"""

Expand Down
56 changes: 56 additions & 0 deletions contracts/scw/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[package]
name = "scw"
version = "0.1.0"
authors = ["bataotaku"]
edition = "2021"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[profile.release]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1
panic = 'abort'
incremental = false
overflow-checks = true

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[package.metadata.scripts]
optimize = """docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.12.10
"""

[dependencies]
cosmwasm-schema = "1.1.3"
cosmwasm-std = "1.1.3"
cosmwasm-storage = "1.3.2"
cw-storage-plus = "1.0.1"
cw2 = "1.0.1"
osmosis-std = "0.16.1"
schemars = "0.8.10"
prost = {version = "0.11.2", default-features = false, features = ["prost-derive"]}
serde = { version = "1.0.145", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.31" }
sha2 = "0.10"

[dev-dependencies]
cw-multi-test = "0.16.2"
10 changes: 10 additions & 0 deletions contracts/scw/src/bin/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use cosmwasm_schema::write_api;

use entrypoint::msg::{ExecuteMsg, InstantiateMsg};

fn main() {
write_api! {
instantiate: InstantiateMsg,
execute: ExecuteMsg,
}
}
151 changes: 151 additions & 0 deletions contracts/scw/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint64,
};
use cw2::set_contract_version;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, BatchUserOp};
use crate::state::USER_NONCE;
use sha2::{Digest, Sha256};

// version info for migration info
const CONTRACT_NAME: &str = "crates.io:wise-wallet";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
Ok(Response::new()
.add_attribute("method", "instantiate")
.add_attribute("owner", info.sender))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::HandleUserOps { UserOps } => execute::handle_batch_user_op(deps, UserOps),
}
}

pub mod execute {
use std::vec;

use cosmwasm_std::CosmosMsg;
use crate::msg::BatchUserOp;

use super::*;
pub fn handle_batch_user_op(
deps: DepsMut,
batch_op: BatchUserOp,
) -> Result<Response, ContractError> {
let mut msgs: Vec<CosmosMsg> = Vec::new();

// Check the nonce once for the entire batch
let usernonce = USER_NONCE
.load(deps.storage, batch_op.Sender)
.unwrap_or_default();
if usernonce + 1 != batch_op.Nonce.u128() {
return Err(ContractError::InvalidNonce {
user: batch_op.Sender.to_string(),
});
}

// Construct a piece of data representing the entire batch to verify the signature
let mut all_bin_msgs = Vec::new();
for op in &batch_op.Ops {
let msg: CosmosMsg<_> = CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute {
contract_addr: op.To.into_string(),
msg: op.Calldata.clone(),
funds: op.funds.clone(),
});
all_bin_msgs.push(to_binary(&msg)?);
msgs.push(msg);
}

let combined_data: Vec<u8> = all_bin_msgs.into_iter().flat_map(|b| b.0).collect();
let hash = sha256(&combined_data);
let sig = batch_op.Signature.clone().unwrap();

if !deps
.api
.secp256k1_verify(&hash, &sig, &batch_op.Pubkey)
.unwrap_or_default()
{
return Err(ContractError::Unauthorized {});
}

Ok(Response::new().add_messages(msgs))
}

}

pub fn sha256(msg: &[u8]) -> Result<Vec<u8>, der::error::Error> {
let mut hasher = Sha256::new();
hasher.update(msg);
let result = hasher.finalize().to_vec();
Ok(result)
}


#[cfg(test)]
mod tests {
use super::*;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{coins, from_binary, Addr, Uint128};
use crate::msg::SingleUserOp;

#[test]
fn test_handle_batch_user_op() {
let mut deps = mock_dependencies();
let env = mock_env();
let sender = "sender".to_string();
let info = mock_info(&sender, &coins(1000, "earth"));

// Create a mock BatchUserOp
let ops = BatchUserOp {
Sender: Addr::unchecked(sender.clone()),
Ops: vec![
SingleUserOp {
To: Addr::unchecked("contract1"),
Calldata: Binary::from(b"do something".to_vec()),
funds: coins(500, "earth"),
},
SingleUserOp {
To: Addr::unchecked("contract2"),
Calldata: Binary::from(b"do something else".to_vec()),
funds: coins(300, "earth"),
},
],
Nonce: Uint128::from(1u64),
Signature: Some(Binary::from(b"fake_signature".to_vec())),
Pubkey: Binary::from(b"fake_pubkey".to_vec()),
};

let execute_msg = ExecuteMsg::HandleUserOps { UserOps: ops };

// Call the execute function
let result = execute(deps.as_mut(), env.clone(), info.clone(), execute_msg);

// Assert Unauthorized error due to fake signature
assert_eq!(
result.unwrap_err(),
ContractError::Unauthorized {}
);

// Additional assertions can be added as required based on the logic
// For example, you can store and query data similar to the provided test,
// and check the expected results.
}
}
14 changes: 14 additions & 0 deletions contracts/scw/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use cosmwasm_std::StdError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),

#[error("Unauthorized")]
Unauthorized {},

#[error("Invalid Nonce for user {user}")]
InvalidNonce { user: String },
}
5 changes: 5 additions & 0 deletions contracts/scw/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod contract;
mod error;
pub mod msg;
pub mod state;
pub use crate::error::ContractError;
26 changes: 26 additions & 0 deletions contracts/scw/src/msg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Binary, Uint128, Uint64, Coin};

#[cw_serde]
pub struct InstantiateMsg {}

#[cw_serde]
pub enum ExecuteMsg {
HandleUserOps { UserOps: BatchUserOp },
}

#[cw_serde]
pub struct SingleUserOp {
pub To: Addr,
pub Calldata: Binary,
pub funds: Vec<Coin>,
}

#[cw_serde]
pub struct BatchUserOp {
pub Sender: Addr,
pub Ops: Vec<SingleUserOp>,
pub Nonce: Uint128,
pub Signature: Option<Binary>,
pub Pubkey: Binary,
}
7 changes: 7 additions & 0 deletions contracts/scw/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use cosmwasm_std::Addr;
use cw_storage_plus::{Item, Map};

pub const USER_NONCE: Map<Addr, u128> = Map::new("USER_NONCE");
Loading

0 comments on commit 8dfbb1e

Please sign in to comment.