forked from 0xekez/cw721-proxy
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlib.rs
126 lines (113 loc) · 3.59 KB
/
lib.rs
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
use cw_paginate_storage::paginate_map_keys;
use cw_storage_plus::{Item, Map};
use cosmwasm_std::{
Addr, Api, Deps, IbcPacket, MessageInfo, Order, Response, StdError, StdResult, Storage,
};
use ics721_types::ibc_types::NonFungibleTokenPacketData;
use thiserror::Error;
const ORIGIN: Item<Addr> = Item::new("origin");
const CHANNELS: Map<String, String> = Map::new("channels");
#[derive(Error, Debug, PartialEq)]
pub enum IncomingProxyError {
#[error(transparent)]
Std(#[from] StdError),
#[error("Unauthorized channel: {0}")]
UnauthorizedChannel(String),
#[error("Sender is not origin contract: {0}")]
UnauthorizedOrigin(String),
}
pub trait IncomingProxyExecute {
fn initialize(
&self,
storage: &mut dyn Storage,
api: &dyn Api,
origin: Option<String>,
channels: Option<Vec<String>>,
) -> StdResult<()> {
if let Some(origin) = origin {
ORIGIN.save(storage, &api.addr_validate(&origin)?)?;
}
if let Some(channels) = channels {
for channel in channels {
CHANNELS.save(storage, channel.clone(), &channel)?;
}
}
Ok(())
}
fn execute_ics721_receive_packet_msg<T>(
&self,
storage: &mut dyn Storage,
info: &MessageInfo,
packet: IbcPacket,
_data: NonFungibleTokenPacketData,
) -> Result<Response<T>, IncomingProxyError> {
self.assert_origin(storage, info.sender.to_string())?;
self.assert_packet_data(storage, packet)?;
Ok(Response::default()
.add_attribute("method", "execute")
.add_attribute("action", "ics721_receive_packet_msg"))
}
fn assert_origin(
&self,
storage: &dyn Storage,
sender: String,
) -> Result<(), IncomingProxyError> {
if let Some(origin) = ORIGIN.may_load(storage)? {
if origin == sender {
return Ok(());
}
}
Err(IncomingProxyError::UnauthorizedOrigin(sender))
}
fn assert_packet_data(
&self,
storage: &dyn Storage,
packet: IbcPacket,
) -> Result<(), IncomingProxyError> {
if CHANNELS.has(storage, packet.dest.channel_id.clone()) {
return Ok(());
}
Err(IncomingProxyError::UnauthorizedChannel(
packet.dest.channel_id,
))
}
fn migrate(
&mut self,
storage: &mut dyn Storage,
api: &dyn Api,
origin: Option<String>,
channels: Option<Vec<String>>,
) -> StdResult<Response> {
if let Some(origin) = origin.clone() {
ORIGIN.save(storage, &api.addr_validate(&origin)?)?;
}
if let Some(channels) = channels.clone() {
CHANNELS.clear(storage);
for channel in channels {
CHANNELS.save(storage, channel.clone(), &channel)?;
}
}
Ok(Response::default()
.add_attribute("method", "migrate")
.add_attribute("origin", origin.unwrap_or("not migrated".to_string()))
.add_attribute(
"channels",
channels.map_or("not migrated".to_string(), |v| v.join(",")),
))
}
}
pub trait IncomingProxyQuery {
fn get_channels(
&self,
deps: Deps,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<Vec<String>> {
paginate_map_keys(deps, &CHANNELS, start_after, limit, Order::Ascending)
}
fn get_origin(&self, storage: &dyn Storage) -> StdResult<Option<Addr>> {
ORIGIN.may_load(storage)
}
}
#[cfg(test)]
mod tests;