Skip to content

Conversation

@Luivatra
Copy link

@Luivatra Luivatra commented Sep 9, 2025

We use the extension functionality of the settings datum to define default protocol fee basis points and allow the treasury admin to change it on a specific pool

The intended usage of the extensions field was not fully clear so I now made a setup with each extension pointing to a potential future extension, in essence creating a linked list, but perhaps there is a more simple setup I overlooked.

Also in this PR: The initial liquidity is now the sum invariant divided by the precision rather than just the sum invariant to avoid very large amounts potentially causing issues in poorly written off chain code.

@Quantumplation
Copy link
Member

Actually, you don't need to do the linked list trick;

Because fields in a struct are already a linked list, and I'm 90% sure that Aiken scripts will just ignore extra fields when deserializing (we should double check this). So we can just make settings a struct, and keep adding to it and old scripts will continue to work.

If that doesn't work, we should make it a Pairs<int, Data> and have a registry of indices for different settings objects, so we don't have to traverse many layers down in our IDE.

For example, 0 would be stablecoin settings, 1 would be permissioned pool settings, etc.

@Luivatra
Copy link
Author

I tried your first suggestion, will push the test case so you can verify I tested it correctly, it crashed on it.
For the second one a List could also work?

@Luivatra
Copy link
Author

Luivatra commented Sep 16, 2025

Example of the suggested method:

pub type SettingsDatumOld {
  some_setting: Int,
  extensions: Data,
}

pub type SettingsDatumNew {
  some_setting: Int,
  new_setting: Int,
  extensions: Data,
}

test convert_new_to_old_settings_datum() {
  let new_datum =
    SettingsDatumNew { some_setting: 42, new_setting: 100, extensions: Void }
  expect Some(new_data) = deserialise(serialise(new_datum))
  expect _old_datum: SettingsDatumOld = new_data
  True
}

test convert_old_to_old_settings_datum() {
  let new_datum = SettingsDatumOld { some_setting: 42, extensions: Void }
  expect Some(new_data) = deserialise(serialise(new_datum))
  expect _old_datum: SettingsDatumOld = new_data
  True
}

Gives the following result:

┍━ tests/examples/ex_settings ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    │ FAIL [mem: 121892, cpu: 32730610] convert_new_to_old_settings_datum
    │ · with traces
    │ | the validator crashed / exited prematurely
    │ | expect _old_datum: SettingsDatumOld = new_data
    │ PASS [mem: 116093, cpu: 29506053] convert_old_to_old_settings_datum
    ┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2 tests | 1 passed | 1 failed

@Quantumplation
Copy link
Member

A list would require that we always have each setting in the list, which maybe makes sense 🤔

@Luivatra
Copy link
Author

A list would require that we always have each setting in the list, which maybe makes sense 🤔

Worst case if we want to "delete" a setting we could replace it with a Void, I did already implement the Pairs version though. Maybe in the end Pairs gives more flexibility for some future usecase. I think we can go with Pairs

/// The name of the token that authenticates the settings UTXO
pub const settings_nft_name: AssetName = "settings"

pub fn find_protocol_fee_extension(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the first thing we do is fail when this isn't set (via expect Some(...)), we could probably just name this must_find_protocol_fee_extension and simplify the code.

but it's not a major deal.

@Luivatra Luivatra merged commit 5d32fce into pi/stableswap Oct 2, 2025
1 check passed
@Luivatra Luivatra deleted the luivatra/fix-protocol-fees-management branch October 2, 2025 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants