Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ac805e3
Add ICRC-106 to supported standards in ICRC ledger
mbjorkqvist Nov 27, 2024
686aad3
Add new types to icrc-ledger-types
mbjorkqvist Nov 27, 2024
48d8100
Add index_principal to upgrade args and add new endpoint
mbjorkqvist Nov 27, 2024
9d6cdb9
Add index principal to metadata
mbjorkqvist Nov 27, 2024
2308795
Clippy
mbjorkqvist Nov 27, 2024
62bfaf6
Candid fixes and renaming
mbjorkqvist Nov 28, 2024
a08bb40
Clippy
mbjorkqvist Nov 28, 2024
23df570
Cleanup
mbjorkqvist Nov 28, 2024
18b1b7b
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Dec 19, 2024
ab9c2d0
Support setting index canister ID in ledger init arguments
mbjorkqvist Dec 19, 2024
d59a44c
Fixes
mbjorkqvist Dec 19, 2024
509ab75
Clippy
mbjorkqvist Dec 19, 2024
d24347a
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Mar 26, 2025
3b4cc30
Missing field
mbjorkqvist Mar 26, 2025
269a2c6
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Apr 1, 2025
e91b839
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Apr 2, 2025
9b6bc0c
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Apr 8, 2025
5631a5c
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Apr 8, 2025
09467c9
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Apr 15, 2025
801001d
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Apr 16, 2025
59c27ed
Set index principal for new chain fusion ledgers
mbjorkqvist Apr 17, 2025
f794544
Set index principal for new SNS ledgers
mbjorkqvist Apr 17, 2025
56e4d71
Fix ledger suite orchestrator tests
mbjorkqvist Apr 17, 2025
3ea51bc
Address review comments
mbjorkqvist Apr 17, 2025
361943c
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 15, 2025
5f5fcd5
Add serde_default to new index_principal field in Ledger struct
mbjorkqvist May 16, 2025
f78f6fd
Beautify code
mbjorkqvist May 16, 2025
b3ec415
Clean up and improve tests
mbjorkqvist May 16, 2025
d993000
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 16, 2025
3f3699f
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 16, 2025
b97325f
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 19, 2025
4f1b0f9
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 20, 2025
a981f60
Uncomment annotation
mbjorkqvist May 21, 2025
79f17e3
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 21, 2025
d1c494a
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist May 26, 2025
91796d5
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Jun 2, 2025
58460e9
Added SNS governance unreleased_changelog.md entry
mbjorkqvist Jun 6, 2025
413b9c6
Bump ICRC ledger size limit
mbjorkqvist Jun 6, 2025
6a7e93a
Merge branch 'master' into mathias-FI-1592-implement-icrc106-in-icrc-…
mbjorkqvist Jun 6, 2025
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
11 changes: 11 additions & 0 deletions packages/icrc-ledger-types/src/icrc106/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use candid::{CandidType, Deserialize, Nat};
use serde::Serialize;

#[derive(Debug, CandidType, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum Icrc106Error {
IndexPrincipalNotSet,
GenericError {
error_code: Nat,
description: String,
},
}
1 change: 1 addition & 0 deletions packages/icrc-ledger-types/src/icrc106/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod errors;
1 change: 1 addition & 0 deletions packages/icrc-ledger-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod icrc;
pub mod icrc1;
pub mod icrc103;
pub mod icrc106;
pub mod icrc2;
pub mod icrc21;
pub mod icrc3;
7 changes: 4 additions & 3 deletions publish/canisters/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ DEFAULT_CANISTERS_MAX_SIZE_E5_BYTES = 21

CANISTERS_MAX_SIZE_COMPRESSED_E5_BYTES = {
# -- FI team --
# The compressed version of these two canisters should be ~600kb,
# we are setting the check to 7 to leave some space for growth
# The compressed version of these two canisters should be ~700kb,
# we are setting the check to 8 to leave some space for growth
# but enough to get an alert in case of a spike in size.
"ic-icrc1-ledger.wasm.gz": 7,
# The size is currently at 701737 bytes.
"ic-icrc1-ledger.wasm.gz": 8,
# The size is currently at 704585 bytes.
"ic-icrc1-ledger-u256.wasm.gz": 8,
# Size when constraint addded: 841_234 bytes
Expand Down
9 changes: 6 additions & 3 deletions rs/ethereum/ledger-suite-orchestrator/src/scheduler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,9 @@ async fn install_ledger_suite<R: CanisterRuntime>(
let ledger_canister_id =
create_canister_once::<Ledger, _>(&args.contract, runtime, cycles_for_ledger_creation)
.await?;
let index_principal =
create_canister_once::<Index, _>(&args.contract, runtime, cycles_for_index_creation)
.await?;

let more_controllers = read_state(|s| s.more_controller_ids().to_vec())
.into_iter()
Expand All @@ -848,14 +851,12 @@ async fn install_ledger_suite<R: CanisterRuntime>(
runtime.id().into(),
more_controllers,
cycles_for_archive_creation,
index_principal,
)),
runtime,
)
.await?;

let _index_principal =
create_canister_once::<Index, _>(&args.contract, runtime, cycles_for_index_creation)
.await?;
let index_arg = Some(IndexArg::Init(IndexInitArg {
ledger_id: ledger_canister_id,
retrieve_blocks_from_ledger_interval_seconds: None,
Expand Down Expand Up @@ -898,6 +899,7 @@ fn icrc1_ledger_init_arg(
archive_controller_id: PrincipalId,
archive_more_controller_ids: Vec<PrincipalId>,
cycles_for_archive_creation: Nat,
index_principal: Principal,
) -> LedgerInitArgs {
use ic_icrc1_ledger::FeatureFlags as LedgerFeatureFlags;
use icrc_ledger_types::icrc::generic_metadata_value::MetadataValue as LedgerMetadataValue;
Expand Down Expand Up @@ -932,6 +934,7 @@ fn icrc1_ledger_init_arg(
),
max_memo_length: Some(MAX_MEMO_LENGTH),
feature_flags: Some(ICRC2_FEATURE),
index_principal: Some(index_principal),
}
}

Expand Down
87 changes: 67 additions & 20 deletions rs/ethereum/ledger-suite-orchestrator/src/scheduler/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,34 +189,28 @@ async fn should_not_retry_successful_operation_after_failing_one() {
let mut runtime = MockCanisterRuntime::new();

runtime.expect_id().return_const(ORCHESTRATOR_PRINCIPAL);
let expected_error = CallError {
method: "create_canister".to_string(),
reason: Reason::OutOfCycles,
};
expect_create_canister_returning(
&mut runtime,
vec![ORCHESTRATOR_PRINCIPAL],
vec![Ok(LEDGER_PRINCIPAL)],
vec![Err(expected_error.clone())],
);
let expected_error = CallError {
method: "install_code".to_string(),
reason: Reason::OutOfCycles,
};
runtime
.expect_install_code()
.times(1)
.return_const(Err(expected_error.clone()));

let task = TaskExecution {
task_type: Task::InstallLedgerSuite(usdc_install_args()),
execute_at_ns: 0,
};
assert_eq!(
task.execute(&runtime).await,
Err(TaskError::InstallCodeError(expected_error))
Err(TaskError::CanisterCreationError(expected_error))
);
assert_eq!(
read_state(|s| s.managed_canisters(&usdc_token_id()).cloned()),
Some(Canisters {
ledger: Some(LedgerCanister::new(ManagedCanisterStatus::Created {
canister_id: LEDGER_PRINCIPAL
})),
ledger: None,
index: None,
archives: vec![],
metadata: usdc_metadata(),
Expand All @@ -229,23 +223,25 @@ async fn should_not_retry_successful_operation_after_failing_one() {
method: "create_canister".to_string(),
reason: Reason::OutOfCycles,
};
runtime.expect_install_code().times(1).return_const(Ok(()));
expect_create_canister_returning(
&mut runtime,
vec![ORCHESTRATOR_PRINCIPAL],
vec![Err(expected_error.clone())],
vec![Ok(LEDGER_PRINCIPAL), Err(expected_error.clone())],
);

let task = TaskExecution {
task_type: Task::InstallLedgerSuite(usdc_install_args()),
execute_at_ns: 0,
};
assert_eq!(
task.execute(&runtime).await,
Err(TaskError::CanisterCreationError(expected_error))
);
assert_eq!(
read_state(|s| s.managed_canisters(&usdc_token_id()).cloned()),
Some(Canisters {
ledger: Some(LedgerCanister::new(ManagedCanisterStatus::Installed {
canister_id: LEDGER_PRINCIPAL,
installed_wasm_hash: read_ledger_wasm_hash(),
ledger: Some(LedgerCanister::new(ManagedCanisterStatus::Created {
canister_id: LEDGER_PRINCIPAL
})),
index: None,
archives: vec![],
Expand All @@ -269,6 +265,36 @@ async fn should_not_retry_successful_operation_after_failing_one() {
.times(1)
.return_const(Err(expected_error.clone()));

let task = TaskExecution {
task_type: Task::InstallLedgerSuite(usdc_install_args()),
execute_at_ns: 0,
};
assert_eq!(
task.execute(&runtime).await,
Err(TaskError::InstallCodeError(expected_error))
);
assert_eq!(
read_state(|s| s.managed_canisters(&usdc_token_id()).cloned()),
Some(Canisters {
ledger: Some(LedgerCanister::new(ManagedCanisterStatus::Created {
canister_id: LEDGER_PRINCIPAL
})),
index: Some(IndexCanister::new(ManagedCanisterStatus::Created {
canister_id: INDEX_PRINCIPAL
})),
archives: vec![],
metadata: usdc_metadata(),
})
);

runtime.checkpoint();
runtime.expect_id().return_const(ORCHESTRATOR_PRINCIPAL);
let expected_error = CallError {
method: "install_code".to_string(),
reason: Reason::OutOfCycles,
};
expect_install_code_returning(&mut runtime, vec![Ok(()), Err(expected_error.clone())]);

assert_eq!(
task.execute(&runtime).await,
Err(TaskError::InstallCodeError(expected_error))
Expand Down Expand Up @@ -325,7 +351,7 @@ async fn should_discard_add_erc20_task_when_ledger_wasm_not_found() {
expect_create_canister_returning(
&mut runtime,
vec![ORCHESTRATOR_PRINCIPAL],
vec![Ok(LEDGER_PRINCIPAL)],
vec![Ok(LEDGER_PRINCIPAL), Ok(INDEX_PRINCIPAL)],
);

assert_eq!(
Expand All @@ -340,7 +366,9 @@ async fn should_discard_add_erc20_task_when_ledger_wasm_not_found() {
ledger: Some(LedgerCanister::new(ManagedCanisterStatus::Created {
canister_id: LEDGER_PRINCIPAL
})),
index: None,
index: Some(IndexCanister::new(ManagedCanisterStatus::Created {
canister_id: INDEX_PRINCIPAL
})),
archives: vec![],
metadata: usdc_metadata(),
})
Expand Down Expand Up @@ -1488,6 +1516,25 @@ fn expect_create_canister_returning(
});
}

fn expect_install_code_returning(
runtime: &mut MockCanisterRuntime,
results: Vec<Result<(), CallError>>,
) {
assert!(!results.is_empty(), "must return at least one result");
let mut install_code_call_counter = 0_usize;
runtime
.expect_install_code()
.times(results.len())
.returning(move |_canister_id, _wasm, _args| {
if install_code_call_counter >= results.len() {
panic!("install_code called too many times!");
}
let result = results[install_code_call_counter].clone();
install_code_call_counter += 1;
result
});
}

fn expect_call_canister_add_ckerc20_token(
runtime: &mut MockCanisterRuntime,
expected_canister_id: Principal,
Expand Down
11 changes: 9 additions & 2 deletions rs/ethereum/ledger-suite-orchestrator/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ fn should_spawn_ledger_with_correct_init_args() {
};

let orchestrator = LedgerSuiteOrchestrator::default();
orchestrator
let managed_canisters_assert = orchestrator
.add_erc20_token(AddErc20Arg {
contract: usdc_erc20_contract(),
ledger_init_arg: realistic_usdc_ledger_init_arg,
})
.expect_new_ledger_and_index_canisters()
.expect_new_ledger_and_index_canisters();
let index_id = managed_canisters_assert.canister_ids.index.unwrap();
assert_eq!(index_id, "ryjl3-tyaaa-aaaaa-aaaba-cai".parse().unwrap());
managed_canisters_assert
.assert_ledger_icrc1_fee(2_000_000_000_000_u64)
.assert_ledger_icrc1_decimals(6_u8)
.assert_ledger_icrc1_name("USD Coin")
Expand Down Expand Up @@ -84,6 +87,10 @@ fn should_spawn_ledger_with_correct_init_args() {
"icrc103:max_take_value".to_string(),
LedgerMetadataValue::from(500u64),
),
(
"icrc106:index_principal".to_string(),
LedgerMetadataValue::from("ryjl3-tyaaa-aaaaa-aaaba-cai"),
),
]);
}

Expand Down
1 change: 1 addition & 0 deletions rs/ledger_suite/icrc1/index-ng/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fn upgrade_ledger(
max_memo_length: None,
feature_flags: None,
change_archive_options: None,
index_principal: None,
}));
env.upgrade_canister(ledger_id, ledger_wasm(), Encode!(&args).unwrap())
.unwrap()
Expand Down
19 changes: 19 additions & 0 deletions rs/ledger_suite/icrc1/ledger/ledger.did
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ type InitArgs = record {
controller_id : principal;
more_controller_ids : opt vec principal;
};
index_principal : opt principal;
};

type ChangeFeeCollector = variant {
Expand All @@ -143,6 +144,7 @@ type UpgradeArgs = record {
max_memo_length : opt nat16;
feature_flags : opt FeatureFlags;
change_archive_options : opt ChangeArchiveOptions;
index_principal : opt principal;
};

type LedgerArg = variant {
Expand Down Expand Up @@ -506,6 +508,21 @@ type icrc103_get_allowances_response = variant {
Err: GetAllowancesError;
};

type GetIndexPrincipalResult = variant {
Ok : principal;
Err : GetIndexPrincipalError;
};

type GetIndexPrincipalError = variant {
IndexPrincipalNotSet;

// Any error not covered by the above variants.
GenericError: record {
error_code: nat;
description: text;
};
};

service : (ledger_arg : LedgerArg) -> {
archives : () -> (vec ArchiveInfo) query;
get_transactions : (GetTransactionsRequest) -> (GetTransactionsResponse) query;
Expand Down Expand Up @@ -537,5 +554,7 @@ service : (ledger_arg : LedgerArg) -> {

icrc103_get_allowances : (GetAllowancesArgs) -> (icrc103_get_allowances_response) query;

icrc106_get_index_principal: () -> (GetIndexPrincipalResult) query;

is_ledger_ready: () -> (bool) query;
}
Loading