Skip to content

Commit

Permalink
feat: merged icp-proxy branch, updated logic for ledger ID, fixed tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alenmestrov committed Dec 4, 2024
2 parents b09edde + 601293a commit 9a8dcb6
Show file tree
Hide file tree
Showing 17 changed files with 595 additions and 501 deletions.
20 changes: 20 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ members = [
"./contracts/test-counter",
"./contracts/icp/context-config",
"./contracts/icp/proxy-contract",
"./contracts/icp/proxy-contract/mock/ledger",
"./contracts/icp/proxy-contract/mock/external",

"./e2e-tests",
]
Expand Down
26 changes: 11 additions & 15 deletions contracts/icp/context-config/build.sh
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
#!/bin/bash

# Exit on error
#!/bin/sh
set -e

# Ensure we have the wasm32 target
rustup target add wasm32-unknown-unknown
cd "$(dirname $0)"

# Build the contract
cargo build --target wasm32-unknown-unknown --release
TARGET="${CARGO_TARGET_DIR:-./target}"

rustup target add wasm32-unknown-unknown

# Generate the candid interface
candid-extractor target/wasm32-unknown-unknown/release/context_contract.wasm > context_contract.did
cargo build --target wasm32-unknown-unknown --profile app-release

# Stop the replica
dfx stop
mkdir -p res

# Start the replica
dfx start --background
cp $TARGET/wasm32-unknown-unknown/app-release/context_contract.wasm ./res/context_contract.wasm

# Deploy the contract
dfx deploy
if command -v wasm-opt > /dev/null; then
wasm-opt -Oz ./res/context_contract.wasm -o ./res/context_contract.wasm
fi
16 changes: 16 additions & 0 deletions contracts/icp/context-config/deploy_devnet.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

# Build the contract
bash ./build.sh

# Generate the candid interface
candid-extractor res/context_contract.wasm > context_contract.did

# Stop the replica
dfx stop

# Start the replica
dfx start --background

# Deploy the contract
dfx deploy
2 changes: 2 additions & 0 deletions contracts/icp/context-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct ContextConfigs {
pub contexts: HashMap<ICContextId, Context>,
pub proxy_code: Option<Vec<u8>>,
pub owner: Principal,
pub ledger_id: Principal,
}

impl Default for ContextConfigs {
Expand All @@ -34,6 +35,7 @@ impl Default for ContextConfigs {
contexts: HashMap::new(),
proxy_code: None,
owner: ic_cdk::api::caller(),
ledger_id: Principal::anonymous(),
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion contracts/icp/context-config/src/mutate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ async fn deploy_proxy_contract(context_id: &ICContextId) -> Result<Principal, St
.with(|configs| configs.borrow().proxy_code.clone())
.ok_or("proxy code not set")?;

// Get the ledger ID
let ledger_id = CONTEXT_CONFIGS
.with(|configs| configs.borrow().ledger_id.clone());
// Create canister with cycles
let create_args = CreateCanisterArgument {
settings: Some(CanisterSettings {
Expand All @@ -119,7 +122,7 @@ async fn deploy_proxy_contract(context_id: &ICContextId) -> Result<Principal, St
let canister_id = canister_record.canister_id;

// Encode init args matching the proxy's init(context_id: ICContextId, ledger_id: Principal)
let init_args = candid::encode_args((context_id.clone(), Principal::anonymous()))
let init_args = candid::encode_args((context_id.clone(), ledger_id))
.map_err(|e| format!("Failed to encode init args: {}", e))?;

let install_args = InstallCodeArgument {
Expand Down
5 changes: 4 additions & 1 deletion contracts/icp/context-config/src/sys.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use candid::Principal;

use crate::CONTEXT_CONFIGS;

#[ic_cdk::update]
pub fn set_proxy_code(proxy_code: Vec<u8>) -> Result<(), String> {
pub fn set_proxy_code(proxy_code: Vec<u8>, ledger_id: Principal) -> Result<(), String> {
CONTEXT_CONFIGS.with(|configs| {
let mut configs = configs.borrow_mut();

Expand All @@ -10,6 +12,7 @@ pub fn set_proxy_code(proxy_code: Vec<u8>) -> Result<(), String> {
return Err("Unauthorized: only owner can set proxy code".to_string());
}

configs.ledger_id = ledger_id;
configs.proxy_code = Some(proxy_code);
Ok(())
})
Expand Down
12 changes: 4 additions & 8 deletions contracts/icp/context-config/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ use rand::Rng;

fn setup() -> (PocketIc, Principal) {
let pic = PocketIc::new();

// Deploy the context contract
let wasm = std::fs::read("target/wasm32-unknown-unknown/release/context_contract.wasm")
.expect("failed to read wasm");
let wasm = std::fs::read("res/context_contract.wasm").expect("failed to read wasm");
let canister = pic.create_canister();
pic.add_cycles(canister, 1_000_000_000_000_000);
pic.install_canister(
Expand All @@ -26,10 +23,9 @@ fn setup() -> (PocketIc, Principal) {
);

// Set the proxy code
let proxy_code = std::fs::read(
"../proxy-contract/target/wasm32-unknown-unknown/release/proxy_contract.wasm",
)
.expect("failed to read proxy wasm");
let proxy_code = std::fs::read("../proxy-contract/res/proxy_contract.wasm").expect(
"failed to read proxy wasm",
);
pic.update_call(
canister,
Principal::anonymous(),
Expand Down
23 changes: 11 additions & 12 deletions contracts/icp/proxy-contract/build.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
#!/bin/bash

# Exit on error
#!/bin/sh
set -e

# Ensure we have the wasm32 target
cd "$(dirname $0)"

TARGET="${CARGO_TARGET_DIR:-./target}"

rustup target add wasm32-unknown-unknown

# Build the contract
cargo build --target wasm32-unknown-unknown --release
cargo build --target wasm32-unknown-unknown --profile app-release

# Generate the candid interface
candid-extractor target/wasm32-unknown-unknown/release/proxy_contract.wasm > proxy_contract.did
mkdir -p res

# Stop the replica
dfx stop
cp $TARGET/wasm32-unknown-unknown/app-release/proxy_contract.wasm ./res/proxy_contract.wasm

# Start the replica
dfx start --background
if command -v wasm-opt > /dev/null; then
wasm-opt -Oz ./res/proxy_contract.wasm -o ./res/proxy_contract.wasm
fi
33 changes: 26 additions & 7 deletions contracts/icp/proxy-contract/build_mock_contracts.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
cd "mock/ledger"
cargo build --target wasm32-unknown-unknown --release
candid-extractor target/wasm32-unknown-unknown/release/mock_ledger.wasm > mock_ledger.did
#!/bin/sh
set -e

cd ../..
# Get the absolute path to the workspace root
WORKSPACE_ROOT="$(cd "$(dirname "$0")/../../../" && pwd)"

cd "mock/external"
cargo build --target wasm32-unknown-unknown --release
candid-extractor target/wasm32-unknown-unknown/release/mock_external.wasm > mock_external.did
cd "$(dirname $0)"

echo "Building proxy contract..."
./build.sh

echo "Building test-ledger contract..."
(cd "$WORKSPACE_ROOT" && cargo build \
--target wasm32-unknown-unknown \
--profile app-release \
-p mock_ledger)
mkdir -p mock/ledger/res
cp "$WORKSPACE_ROOT/target/wasm32-unknown-unknown/app-release/mock_ledger.wasm" mock/ledger/res/

echo "Building test-external contract..."
(cd "$WORKSPACE_ROOT" && cargo build \
--target wasm32-unknown-unknown \
--profile app-release \
-p mock_external)
mkdir -p mock/external/res
cp "$WORKSPACE_ROOT/target/wasm32-unknown-unknown/app-release/mock_external.wasm" mock/external/res/

echo "Building context-config contract..."
(cd ../context-config && ./build.sh)
18 changes: 18 additions & 0 deletions contracts/icp/proxy-contract/mock/external/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh
set -e

cd "$(dirname $0)"

TARGET="${CARGO_TARGET_DIR:-../../target}"

rustup target add wasm32-unknown-unknown

cargo build --target wasm32-unknown-unknown --profile app-release

mkdir -p res

cp $TARGET/wasm32-unknown-unknown/app-release/mock_external.wasm ./res/

if command -v wasm-opt > /dev/null; then
wasm-opt -Oz ./res/mock_external.wasm -o ./res/mock_external.wasm
fi
2 changes: 1 addition & 1 deletion contracts/icp/proxy-contract/mock/external/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ fn get_calls() -> Vec<Vec<u8>> {
CALLS.with(|calls| calls.borrow().clone())
}

ic_cdk::export_candid!();
ic_cdk::export_candid!();
18 changes: 18 additions & 0 deletions contracts/icp/proxy-contract/mock/ledger/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh
set -e

cd "$(dirname $0)"

TARGET="${CARGO_TARGET_DIR:-./target}"

rustup target add wasm32-unknown-unknown

cargo build --target wasm32-unknown-unknown --profile app-release

mkdir -p res

cp $TARGET/wasm32-unknown-unknown/app-release/mock_ledger.wasm ./res/mock_ledger.wasm

if command -v wasm-opt > /dev/null; then
wasm-opt -Oz ./res/mock_ledger.wasm -o ./res/mock_ledger.wasm
fi
36 changes: 20 additions & 16 deletions contracts/icp/proxy-contract/mock/ledger/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::cell::RefCell;

use candid::{CandidType, Deserialize, Principal};
use ic_ledger_types::{Tokens, AccountIdentifier, Memo, TransferArgs, Timestamp, BlockIndex, TransferError};
use ic_ledger_types::{
AccountIdentifier, BlockIndex, Memo, Timestamp, Tokens, TransferArgs, TransferError,
};

thread_local! {
static BALANCE: RefCell<u64> = RefCell::new(1_000_000_000);
Expand All @@ -10,44 +13,45 @@ type TransferResult = Result<BlockIndex, TransferError>;

#[ic_cdk::update]
fn transfer(args: TransferArgs) -> TransferResult {
ic_cdk::println!("Mock ledger received transfer: to={:?}, amount={}",
args.to, args.amount);

ic_cdk::println!(
"Mock ledger received transfer: to={:?}, amount={}",
args.to,
args.amount
);

// Verify fee
if args.fee.e8s() != 10_000 {
return Err(TransferError::BadFee {
expected_fee: Tokens::from_e8s(10_000)
return Err(TransferError::BadFee {
expected_fee: Tokens::from_e8s(10_000),
});
}

let amount_e8s = args.amount.e8s();

BALANCE.with(|balance| {
let mut bal = balance.borrow_mut();

// Check if we have enough balance
if amount_e8s > *bal {
return Err(TransferError::InsufficientFunds {
balance: Tokens::from_e8s(*bal)
return Err(TransferError::InsufficientFunds {
balance: Tokens::from_e8s(*bal),
});
}

// Subtract amount and fee
*bal = bal.saturating_sub(amount_e8s);
*bal = bal.saturating_sub(args.fee.e8s());

ic_cdk::println!("New balance: {}", *bal);

// Return mock block index
Ok(1)
})
}

#[ic_cdk::query]
fn account_balance(args: AccountBalanceArgs) -> Tokens {
BALANCE.with(|balance| {
Tokens::from_e8s(*balance.borrow())
})
BALANCE.with(|balance| Tokens::from_e8s(*balance.borrow()))
}

#[derive(CandidType, Deserialize)]
Expand Down
3 changes: 1 addition & 2 deletions contracts/icp/proxy-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet, HashMap};

use candid::Principal;
use serde::{Deserialize, Serialize};
use types::{ICContextId, LedgerId};

use crate::types::{
Expand All @@ -14,7 +13,7 @@ pub mod mutate;
pub mod query;
pub mod types;

#[derive(Serialize, Deserialize, Default)]
#[derive(Default)]
pub struct ICProxyContract {
pub context_id: ICContextId,
pub context_config_id: String,
Expand Down
Loading

0 comments on commit 9a8dcb6

Please sign in to comment.