Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow P2P swaps of disabled tokens #7057

Merged
merged 6 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions backend/canisters/escrow/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [unreleased]

### Changed

- Disallow P2P swaps of disabled tokens ([#7057](https://github.com/open-chat-labs/open-chat/pull/7057))

## [[2.0.1512](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1512-escrow)] - 2024-12-13

### Added
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/escrow/api/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use types::{BuildVersion, CanisterId};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub registry_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
pub wasm_version: BuildVersion,
pub test_mode: bool,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use candid::CandidType;
use serde::{Deserialize, Serialize};
use types::CanisterId;

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub ledger_canister_id: CanisterId,
pub enabled: bool,
}

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub enum Response {
Success,
}
1 change: 1 addition & 0 deletions backend/canisters/escrow/api/src/updates/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod c2c_set_token_enabled;
pub mod cancel_swap;
pub mod create_swap;
pub mod notify_deposit;
1 change: 1 addition & 0 deletions backend/canisters/escrow/c2c_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use escrow_canister::*;
// Queries

// Updates
generate_c2c_call!(c2c_set_token_enabled);
generate_c2c_call!(create_swap);
generate_c2c_call!(cancel_swap);
generate_c2c_call!(notify_deposit);
9 changes: 9 additions & 0 deletions backend/canisters/escrow/impl/src/guards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate::read_state;

pub fn caller_is_registry_canister() -> Result<(), String> {
if read_state(|state| state.is_caller_registry_canister()) {
Ok(())
} else {
Err("Caller is not the registry canister".to_string())
}
}
19 changes: 17 additions & 2 deletions backend/canisters/escrow/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use canister_state_macros::canister_state;
use canister_timer_jobs::TimerJobs;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use types::{BuildVersion, CanisterId, Cycles, TimestampMillis, Timestamped};
use utils::env::Environment;

mod guards;
mod jobs;
mod lifecycle;
mod memory;
Expand All @@ -34,6 +35,10 @@ impl RuntimeState {
RuntimeState { env, data }
}

pub fn is_caller_registry_canister(&self) -> bool {
self.env.caller() == self.data.registry_canister_id
}

pub fn metrics(&self) -> Metrics {
let now = self.env.now();

Expand All @@ -46,7 +51,9 @@ impl RuntimeState {
git_commit_id: utils::git::git_commit_id().to_string(),
swaps: self.data.swaps.metrics(now),
stable_memory_sizes: memory::memory_sizes(),
disabled_tokens: self.data.disabled_tokens.iter().copied().collect(),
canister_ids: CanisterIds {
registry: self.data.registry_canister_id,
cycles_dispenser: self.data.cycles_dispenser_canister_id,
},
}
Expand All @@ -59,19 +66,25 @@ struct Data {
pub pending_payments_queue: PendingPaymentsQueue,
pub notify_status_change_queue: NotifyStatusChangeQueue,
timer_jobs: TimerJobs<TimerJob>,
#[serde(default = "CanisterId::anonymous")]
pub registry_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
#[serde(default)]
pub disabled_tokens: BTreeSet<CanisterId>,
pub rng_seed: [u8; 32],
pub test_mode: bool,
}

impl Data {
pub fn new(cycles_dispenser_canister_id: CanisterId, test_mode: bool) -> Data {
pub fn new(registry_canister_id: CanisterId, cycles_dispenser_canister_id: CanisterId, test_mode: bool) -> Data {
Data {
swaps: Swaps::default(),
pending_payments_queue: PendingPaymentsQueue::default(),
notify_status_change_queue: NotifyStatusChangeQueue::default(),
timer_jobs: TimerJobs::default(),
registry_canister_id,
cycles_dispenser_canister_id,
disabled_tokens: BTreeSet::new(),
rng_seed: [0; 32],
test_mode,
}
Expand All @@ -88,6 +101,7 @@ pub struct Metrics {
pub git_commit_id: String,
pub swaps: SwapMetrics,
pub stable_memory_sizes: BTreeMap<u8, u64>,
pub disabled_tokens: Vec<CanisterId>,
pub canister_ids: CanisterIds,
}

Expand All @@ -103,5 +117,6 @@ pub struct SwapMetrics {

#[derive(Serialize, Debug)]
pub struct CanisterIds {
pub registry: CanisterId,
pub cycles_dispenser: CanisterId,
}
2 changes: 1 addition & 1 deletion backend/canisters/escrow/impl/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn init(args: Args) {
init_cycles_dispenser_client(args.cycles_dispenser_canister_id, args.test_mode);

let env = init_env([0; 32]);
let data = Data::new(args.cycles_dispenser_canister_id, args.test_mode);
let data = Data::new(args.registry_canister_id, args.cycles_dispenser_canister_id, args.test_mode);

init_state(env, data, args.wasm_version);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use escrow_canister::post_upgrade::Args;
use ic_cdk::post_upgrade;
use stable_memory::get_reader;
use tracing::info;
use types::CanisterId;
use utils::cycles::init_cycles_dispenser_client;

#[post_upgrade]
Expand All @@ -15,9 +16,15 @@ fn post_upgrade(args: Args) {
let memory = get_upgrades_memory();
let reader = get_reader(&memory);

let (data, errors, logs, traces): (Data, Vec<LogEntry>, Vec<LogEntry>, Vec<LogEntry>) =
let (mut data, errors, logs, traces): (Data, Vec<LogEntry>, Vec<LogEntry>, Vec<LogEntry>) =
msgpack::deserialize(reader).unwrap();

if data.test_mode {
data.registry_canister_id = CanisterId::from_text("cglwi-oaaaa-aaaar-aqw4q-cai").unwrap();
} else {
data.registry_canister_id = CanisterId::from_text("cpi5u-yiaaa-aaaar-aqw5a-cai").unwrap();
}

canister_logger::init_with_logs(data.test_mode, errors, logs, traces);

let env = init_env(data.rng_seed);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::guards::caller_is_registry_canister;
use crate::{mutate_state, RuntimeState};
use canister_api_macros::update;
use canister_tracing_macros::trace;
use escrow_canister::c2c_set_token_enabled::{Response::*, *};

#[update(guard = "caller_is_registry_canister", msgpack = true)]
#[trace]
fn c2c_set_token_enabled(args: Args) -> Response {
mutate_state(|state| c2c_set_token_enabled_impl(args, state))
}

fn c2c_set_token_enabled_impl(args: Args, state: &mut RuntimeState) -> Response {
if args.enabled {
state.data.disabled_tokens.remove(&args.ledger_canister_id);
} else {
state.data.disabled_tokens.insert(args.ledger_canister_id);
}
Success
}
16 changes: 10 additions & 6 deletions backend/canisters/escrow/impl/src/updates/create_swap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::timer_job_types::{ExpireSwapJob, TimerJob};
use crate::{mutate_state, RuntimeState};
use crate::{mutate_state, Data, RuntimeState};
use canister_api_macros::update;
use canister_tracing_macros::trace;
use escrow_canister::create_swap::{Response::*, *};
Expand All @@ -13,7 +13,7 @@ fn create_swap(args: Args) -> Response {

fn create_swap_impl(args: Args, state: &mut RuntimeState) -> Response {
let now = state.env.now();
if let Err(error) = validate_swap(&args, now) {
if let Err(error) = validate_swap(&args, now, &state.data) {
InvalidSwap(error)
} else {
let caller = state.env.caller().into();
Expand All @@ -28,15 +28,19 @@ fn create_swap_impl(args: Args, state: &mut RuntimeState) -> Response {
}
}

fn validate_swap(args: &Args, now: TimestampMillis) -> Result<(), String> {
fn validate_swap(args: &Args, now: TimestampMillis, data: &Data) -> Result<(), String> {
if args.token0.ledger == args.token1.ledger {
Err("Token0 must be different to token1".to_string())
Err("Input token must be different to output token".to_string())
} else if args.token0_amount == 0 {
Err("Token0 amount cannot be 0".to_string())
Err("Input amount cannot be 0".to_string())
} else if args.token1_amount == 0 {
Err("Token1 amount cannot be 0".to_string())
Err("Output amount cannot be 0".to_string())
} else if args.expires_at < now {
Err("Expiry cannot be in the past".to_string())
} else if data.disabled_tokens.contains(&args.token0.ledger) {
Err("Input token is disabled for swaps".to_string())
} else if data.disabled_tokens.contains(&args.token1.ledger) {
Err("Output token is disabled for swaps".to_string())
} else {
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/escrow/impl/src/updates/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod c2c_set_token_enabled;
pub mod cancel_swap;
pub mod create_swap;
pub mod notify_deposit;
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/registry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- Expose size of each virtual stable memory in metrics ([#6981](https://github.com/open-chat-labs/open-chat/pull/6981))
- Include the ledger canister Id in transfer failed error logs ([#7011](https://github.com/open-chat-labs/open-chat/pull/7011))
- Disallow P2P swaps of disabled tokens ([#7057](https://github.com/open-chat-labs/open-chat/pull/7057))

## [[2.0.1490](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1490-registry)] - 2024-12-03

Expand Down
1 change: 1 addition & 0 deletions backend/canisters/registry/api/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Args {
pub nns_root_canister_id: CanisterId,
pub sns_wasm_canister_id: CanisterId,
pub nns_index_canister_id: CanisterId,
pub escrow_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
pub wasm_version: BuildVersion,
pub test_mode: bool,
Expand Down
2 changes: 2 additions & 0 deletions backend/canisters/registry/impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ canister_state_macros = { path = "../../../libraries/canister_state_macros" }
canister_tracing_macros = { path = "../../../libraries/canister_tracing_macros" }
constants = { path = "../../../libraries/constants" }
dataurl = { workspace = true }
escrow_canister = { path = "../../escrow/api" }
escrow_canister_c2c_client = { path = "../../escrow/c2c_client" }
futures = { workspace = true }
hex = { workspace = true }
http_request = { path = "../../../libraries/http_request" }
Expand Down
6 changes: 6 additions & 0 deletions backend/canisters/registry/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ impl RuntimeState {
canister_ids: CanisterIds {
proposals_bot: self.data.proposals_bot_canister_id,
sns_wasm: self.data.sns_wasm_canister_id,
escrow: self.data.escrow_canister_id,
cycles_dispenser: self.data.cycles_dispenser_canister_id,
},
}
Expand All @@ -75,6 +76,8 @@ struct Data {
proposals_bot_canister_id: CanisterId,
user_index_canister_id: CanisterId,
sns_wasm_canister_id: CanisterId,
#[serde(default = "CanisterId::anonymous")]
escrow_canister_id: CanisterId,
cycles_dispenser_canister_id: CanisterId,
tokens: Tokens,
nervous_systems: NervousSystems,
Expand All @@ -94,6 +97,7 @@ impl Data {
proposals_bot_canister_id: CanisterId,
user_index_canister_id: CanisterId,
sns_wasm_canister_id: CanisterId,
escrow_canister_id: CanisterId,
cycles_dispenser_canister_id: CanisterId,
test_mode: bool,
) -> Data {
Expand All @@ -102,6 +106,7 @@ impl Data {
proposals_bot_canister_id,
user_index_canister_id,
sns_wasm_canister_id,
escrow_canister_id,
cycles_dispenser_canister_id,
tokens: Tokens::default(),
nervous_systems: NervousSystems::default(),
Expand Down Expand Up @@ -184,5 +189,6 @@ pub struct Metrics {
pub struct CanisterIds {
pub proposals_bot: CanisterId,
pub sns_wasm: CanisterId,
pub escrow: CanisterId,
pub cycles_dispenser: CanisterId,
}
1 change: 1 addition & 0 deletions backend/canisters/registry/impl/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fn init(args: Args) {
args.proposals_bot_canister_id,
args.user_index_canister_id,
args.sns_wasm_canister_id,
args.escrow_canister_id,
args.cycles_dispenser_canister_id,
args.test_mode,
);
Expand Down
40 changes: 38 additions & 2 deletions backend/canisters/registry/impl/src/lifecycle/post_upgrade.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::lifecycle::{init_env, init_state};
use crate::memory::get_upgrades_memory;
use crate::Data;
use crate::{read_state, Data};
use canister_logger::LogEntry;
use canister_tracing_macros::trace;
use ic_cdk::post_upgrade;
use registry_canister::post_upgrade::Args;
use stable_memory::get_reader;
use std::time::Duration;
use tracing::info;
use types::CanisterId;
use utils::cycles::init_cycles_dispenser_client;

#[post_upgrade]
Expand All @@ -15,14 +17,48 @@ fn post_upgrade(args: Args) {
let memory = get_upgrades_memory();
let reader = get_reader(&memory);

let (data, errors, logs, traces): (Data, Vec<LogEntry>, Vec<LogEntry>, Vec<LogEntry>) =
let (mut data, errors, logs, traces): (Data, Vec<LogEntry>, Vec<LogEntry>, Vec<LogEntry>) =
msgpack::deserialize(reader).unwrap();

if data.test_mode {
data.escrow_canister_id = CanisterId::from_text("tspqt-xaaaa-aaaal-qcnna-cai").unwrap();
} else {
data.escrow_canister_id = CanisterId::from_text("s4yi7-yiaaa-aaaar-qacpq-cai").unwrap();
}

canister_logger::init_with_logs(data.test_mode, errors, logs, traces);

let env = init_env(data.rng_seed);
init_cycles_dispenser_client(data.cycles_dispenser_canister_id, data.test_mode);
init_state(env, data, args.wasm_version);

info!(version = %args.wasm_version, "Post-upgrade complete");

ic_cdk_timers::set_timer(Duration::ZERO, || ic_cdk::spawn(set_disabled_tokens_in_escrow_canister()));
}

async fn set_disabled_tokens_in_escrow_canister() {
let (disabled_tokens, escrow_canister_id) = read_state(|state| {
let disabled_tokens: Vec<_> = state
.data
.tokens
.iter()
.filter(|t| !t.enabled)
.map(|t| t.ledger_canister_id)
.collect();

(disabled_tokens, state.data.escrow_canister_id)
});

for ledger_canister_id in disabled_tokens {
escrow_canister_c2c_client::c2c_set_token_enabled(
escrow_canister_id,
&escrow_canister::c2c_set_token_enabled::Args {
ledger_canister_id,
enabled: false,
},
)
.await
.unwrap();
}
}
Loading
Loading