diff --git a/artifacts/stablecoin-idl.json b/artifacts/stablecoin-idl.json index b2e88be..0ed6315 100644 --- a/artifacts/stablecoin-idl.json +++ b/artifacts/stablecoin-idl.json @@ -125,7 +125,7 @@ { "name": "stablecoin_definition", "writable": false, - "signer": false, + "signer": true, "init": false }, { diff --git a/programs/integration_tests/tests/stablecoin.rs b/programs/integration_tests/tests/stablecoin.rs index af61a8e..309fdd7 100644 --- a/programs/integration_tests/tests/stablecoin.rs +++ b/programs/integration_tests/tests/stablecoin.rs @@ -27,6 +27,10 @@ impl Keys { fn user_stablecoin_holding() -> PrivateKey { PrivateKey::try_new([43; 32]).expect("valid private key") } + + fn stablecoin_definition() -> PrivateKey { + PrivateKey::try_new([44; 32]).expect("valid private key") + } } impl Ids { @@ -51,7 +55,9 @@ impl Ids { } fn stablecoin_definition() -> AccountId { - AccountId::new([6; 32]) + AccountId::from(&PublicKey::new_from_private_key( + &Keys::stablecoin_definition(), + )) } fn price_feed() -> AccountId { @@ -486,11 +492,12 @@ fn stablecoin_redemption_controller_initializes_and_updates_from_price_feed() { Ids::stablecoin_definition(), Ids::price_feed(), ], - vec![], + vec![current_nonce(&state, Ids::stablecoin_definition())], initialize, ) .unwrap(); - let witness_set = public_transaction::WitnessSet::for_message(&message, &[]); + let witness_set = + public_transaction::WitnessSet::for_message(&message, &[&Keys::stablecoin_definition()]); let tx = PublicTransaction::new(message, witness_set); state .transition_from_public_transaction(&tx, 0, current_timestamp) diff --git a/programs/stablecoin/core/src/lib.rs b/programs/stablecoin/core/src/lib.rs index cac1a62..336ceb9 100644 --- a/programs/stablecoin/core/src/lib.rs +++ b/programs/stablecoin/core/src/lib.rs @@ -91,7 +91,7 @@ pub enum Instruction { /// Required accounts (3): /// - Redemption controller account (uninitialized, address must match /// `compute_redemption_controller_pda(self_program_id, stablecoin_definition, price_feed)`) - /// - Stablecoin token definition account (initialized fungible token) + /// - Stablecoin token definition account (authorized initialized fungible token) /// - Oracle price feed account (initialized; must decode as the configured /// stablecoin/collateral market price) /// diff --git a/programs/stablecoin/methods/guest/src/bin/stablecoin.rs b/programs/stablecoin/methods/guest/src/bin/stablecoin.rs index d651540..9e25c68 100644 --- a/programs/stablecoin/methods/guest/src/bin/stablecoin.rs +++ b/programs/stablecoin/methods/guest/src/bin/stablecoin.rs @@ -130,6 +130,7 @@ mod stablecoin { ctx: ProgramContext, #[account(init)] controller: AccountWithMetadata, + #[account(signer)] stablecoin_definition: AccountWithMetadata, price_feed: AccountWithMetadata, collateral_definition_id: AccountId, diff --git a/programs/stablecoin/src/redemption_controller.rs b/programs/stablecoin/src/redemption_controller.rs index a42081e..29c8976 100644 --- a/programs/stablecoin/src/redemption_controller.rs +++ b/programs/stablecoin/src/redemption_controller.rs @@ -16,6 +16,7 @@ const CONTROLLER_GAIN_SCALE_I128: i128 = { /// Initialize the redemption-rate feedback controller for one stablecoin/feed pair. /// /// # Panics +/// - `stablecoin_definition` is not authorized. /// - `controller` is already initialized. /// - `controller.account_id` does not match the stablecoin/feed PDA. /// - `stablecoin_definition` is uninitialized or not a fungible token definition. @@ -39,6 +40,10 @@ pub fn initialize_redemption_controller( max_price_feed_age: u64, current_timestamp: u64, ) -> Vec { + assert!( + stablecoin_definition.is_authorized, + "Stablecoin definition authorization is missing" + ); assert_eq!( controller.account, Account::default(), @@ -380,7 +385,7 @@ mod tests { }), nonce: Nonce(0), }, - is_authorized: false, + is_authorized: true, account_id: stablecoin_definition_id(), } } @@ -489,6 +494,28 @@ mod tests { assert_eq!(controller.last_update_timestamp, 100); } + #[test] + #[should_panic(expected = "Stablecoin definition authorization is missing")] + fn initialize_redemption_controller_requires_stablecoin_definition_authorization() { + let mut stablecoin_definition = stablecoin_definition_account(); + stablecoin_definition.is_authorized = false; + + initialize_redemption_controller( + uninit_controller_account(), + stablecoin_definition, + price_feed_account(1_000, 100), + STABLECOIN_PROGRAM_ID, + collateral_definition_id(), + 1_000, + CONTROLLER_GAIN_SCALE, + 0, + 1_000, + 500, + 10, + 100, + ); + } + #[test] fn update_redemption_controller_uses_live_price_feed() { let post_states = update_redemption_controller(