diff --git a/chain-extensions/src/mock.rs b/chain-extensions/src/mock.rs index e3b7eb2e94..ecbf1b6515 100644 --- a/chain-extensions/src/mock.rs +++ b/chain-extensions/src/mock.rs @@ -348,6 +348,8 @@ parameter_types! { pub const LeaseDividendsDistributionInterval: u32 = 100; pub const MaxImmuneUidsPercentage: Percent = Percent::from_percent(80); pub const EvmKeyAssociateRateLimit: u64 = 10; + pub const SubtensorPalletId: PalletId = PalletId(*b"subtensr"); + pub const BurnAccountId: PalletId = PalletId(*b"burntnsr"); } impl pallet_subtensor::Config for Test { @@ -423,6 +425,8 @@ impl pallet_subtensor::Config for Test { type CommitmentsInterface = CommitmentsI; type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit; type AuthorshipProvider = MockAuthorshipProvider; + type SubtensorPalletId = SubtensorPalletId; + type BurnAccountId = BurnAccountId; type WeightInfo = (); } @@ -690,7 +694,7 @@ pub fn register_ok_neuron( let bal: TaoBalance = SubtensorModule::get_coldkey_balance(&cold); if bal < min_balance_needed { - SubtensorModule::add_balance_to_coldkey_account(&cold, min_balance_needed - bal); + add_balance_to_coldkey_account(&cold, min_balance_needed - bal); } }; @@ -727,11 +731,22 @@ pub fn register_ok_neuron( ); } +#[allow(dead_code)] +pub fn add_balance_to_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao).unwrap(); +} + +#[allow(dead_code)] +pub fn remove_balance_from_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let _ = SubtensorModule::burn_tao(coldkey, tao); +} + #[allow(dead_code)] pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost.into()); + add_balance_to_coldkey_account(coldkey, lock_cost.into()); assert_ok!(SubtensorModule::register_network( RawOrigin::Signed(*coldkey).into(), diff --git a/chain-extensions/src/tests.rs b/chain-extensions/src/tests.rs index b8956e8659..4d2285f1d4 100644 --- a/chain-extensions/src/tests.rs +++ b/chain-extensions/src/tests.rs @@ -15,6 +15,8 @@ use substrate_fixed::types::U96F32; use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance, Token}; use subtensor_swap_interface::SwapHandler; +use mock::*; + type AccountId = ::AccountId; #[derive(Clone)] @@ -89,7 +91,7 @@ fn remove_stake_full_limit_success_with_limit_price() { mock::register_ok_neuron(netuid, hotkey, coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey, TaoBalance::from(stake_amount_raw + 1_000_000_000), ); @@ -228,7 +230,7 @@ fn remove_stake_limit_success_respects_price_limit() { mock::register_ok_neuron(netuid, hotkey, coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey, TaoBalance::from(stake_amount_raw + 1_000_000_000), ); @@ -304,10 +306,7 @@ fn add_stake_limit_success_executes_within_price_guard() { mock::register_ok_neuron(netuid, hotkey, coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &coldkey, - (amount_raw + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&coldkey, (amount_raw + 1_000_000_000).into()); let stake_before = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -379,10 +378,7 @@ fn swap_stake_success_moves_between_subnets() { mock::register_ok_neuron(netuid_a, hotkey, coldkey, 0); mock::register_ok_neuron(netuid_b, hotkey, coldkey, 1); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &coldkey, - (stake_amount_raw + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&coldkey, (stake_amount_raw + 1_000_000_000).into()); assert_ok!(pallet_subtensor::Pallet::::add_stake( RawOrigin::Signed(coldkey).into(), @@ -456,10 +452,7 @@ fn transfer_stake_success_moves_between_coldkeys() { mock::register_ok_neuron(netuid, hotkey, origin_coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &origin_coldkey, - (stake_amount_raw + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&origin_coldkey, (stake_amount_raw + 1_000_000_000).into()); assert_ok!(pallet_subtensor::Pallet::::add_stake( RawOrigin::Signed(origin_coldkey).into(), @@ -540,10 +533,7 @@ fn move_stake_success_moves_alpha_between_hotkeys() { mock::register_ok_neuron(netuid, origin_hotkey, coldkey, 0); mock::register_ok_neuron(netuid, destination_hotkey, coldkey, 1); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &coldkey, - (stake_amount_raw + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&coldkey, (stake_amount_raw + 1_000_000_000).into()); assert_ok!(pallet_subtensor::Pallet::::add_stake( RawOrigin::Signed(coldkey).into(), @@ -620,10 +610,7 @@ fn unstake_all_alpha_success_moves_stake_to_root() { ); mock::register_ok_neuron(netuid, hotkey, coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &coldkey, - (stake_amount_raw + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&coldkey, (stake_amount_raw + 1_000_000_000).into()); assert_ok!(pallet_subtensor::Pallet::::add_stake( RawOrigin::Signed(coldkey).into(), @@ -667,10 +654,7 @@ fn add_proxy_success_creates_proxy_relationship() { let delegator = U256::from(6001); let delegate = U256::from(6002); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &delegator, - 1_000_000_000.into(), - ); + add_balance_to_coldkey_account(&delegator, 1_000_000_000.into()); assert_eq!( pallet_subtensor_proxy::Proxies::::get(delegator) @@ -705,10 +689,7 @@ fn remove_proxy_success_removes_proxy_relationship() { let delegator = U256::from(7001); let delegate = U256::from(7002); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &delegator, - 1_000_000_000.into(), - ); + add_balance_to_coldkey_account(&delegator, 1_000_000_000.into()); let mut add_env = MockEnv::new(FunctionId::AddProxyV1, delegator, delegate.encode()); let ret = SubtensorChainExtension::::dispatch(&mut add_env).unwrap(); @@ -842,10 +823,7 @@ fn add_stake_success_updates_stake_and_returns_success_code() { ); mock::register_ok_neuron(netuid, hotkey, coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &coldkey, - amount_raw.into(), - ); + add_balance_to_coldkey_account(&coldkey, amount_raw.into()); assert!( pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey).is_zero() @@ -930,10 +908,7 @@ fn unstake_all_success_unstakes_balance() { ); mock::register_ok_neuron(netuid, hotkey, coldkey, 0); - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &coldkey, - (stake_amount_raw + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&coldkey, (stake_amount_raw + 1_000_000_000).into()); assert_ok!(pallet_subtensor::Pallet::::add_stake( RawOrigin::Signed(coldkey).into(), diff --git a/common/src/lib.rs b/common/src/lib.rs index 70fa42c32b..82aa6a4155 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -246,8 +246,8 @@ pub trait TokenReserve { pub trait BalanceOps { fn tao_balance(account_id: &AccountId) -> TaoBalance; fn alpha_balance(netuid: NetUid, coldkey: &AccountId, hotkey: &AccountId) -> AlphaBalance; - fn increase_balance(coldkey: &AccountId, tao: TaoBalance); - fn decrease_balance(coldkey: &AccountId, tao: TaoBalance) -> Result; + // fn increase_balance(coldkey: &AccountId, tao: TaoBalance); + // fn decrease_balance(coldkey: &AccountId, tao: TaoBalance) -> Result; fn increase_stake( coldkey: &AccountId, hotkey: &AccountId, diff --git a/contract-tests/src/subtensor.ts b/contract-tests/src/subtensor.ts index 2b3b5d8be1..6ad509fe62 100644 --- a/contract-tests/src/subtensor.ts +++ b/contract-tests/src/subtensor.ts @@ -421,6 +421,142 @@ export async function setNetworkLastLockCost(api: TypedApi, defau assert.equal(defaultNetworkLastLockCost, valueOnChain) } +export function getSubnetAccountId(netuid: number): string { + // Hardcode to speed up tests + const NETUID_TO_ACCOUNT_ID: Record = { + 0: "5EYCAe5jLQhn6ofDSvqF6iY53erXNkwhyE1aCEgvi1NNs91F", + 1: "5EYCAe5jLQhn6ofDSvqWqk5fA9XiqK3ahtx5kBNmAqF78mqL", + 2: "5EYCAe5jLQhn6ofDSvqnamdFGeCvHs9TSZtbJ84bdf7qQRc6", + 3: "5EYCAe5jLQhn6ofDSvr4KoAqP8t7kRFLBEq6r4kS6UzZgCb5", + 4: "5EYCAe5jLQhn6ofDSvrL4piRVdZKCyMCuumcQ1SGZJsHwmeE", + 5: "5EYCAe5jLQhn6ofDSvrborG1c8EWfXT5eai7wx8728k2DHK7", + 6: "5EYCAe5jLQhn6ofDSvrsYsobicui85YxPFedVtowUxckUuF8", + 7: "5EYCAe5jLQhn6ofDSvs9HuMBq7auadeq7vb93qVmwnVUkg5A", + 8: "5EYCAe5jLQhn6ofDSvsR2vtmwcG73BkhrbXebnBcQcND2Bdh", + 9: "5EYCAe5jLQhn6ofDSvsgmxSN46wJVjrabGUA9isSsSEwHnFy", + 10: "5EYCAe5jLQhn6ofDSvsxWyyxAbcVxHxTKwQfhfZHLG7fZUJG", + 11: "5EYCAe5jLQhn6ofDSvtEG1XYH6HhQr4L4cMBFcF7o5zPpyA3", + 12: "5EYCAe5jLQhn6ofDSvtW1358PaxtsQACoHHgoYvxFus86kJK", + 13: "5EYCAe5jLQhn6ofDSvtmk4ciW5e6KxG5XxECMVcnijjrN8rz", + 14: "5EYCAe5jLQhn6ofDSvu3V6AJcaKHnWMxGdAhuSJdBZcadwDn", + 15: "5EYCAe5jLQhn6ofDSvuKE7htj4zVF4Tq1J7DTNzTePVJucfX", + 16: "5EYCAe5jLQhn6ofDSvuay9FUqZfghcZhjy3j1KgJ7DN3BDc2", + 17: "5EYCAe5jLQhn6ofDSvuriAo4x4LtAAfaUdzEZGN8a3EmSncG", + 18: "5EYCAe5jLQhn6ofDSvv8TCLf4Z25cimTDJvk7D3y2s7ViZEm", + 19: "5EYCAe5jLQhn6ofDSvvQCDtFB3hH5GsKwysFf9joVgzDytnb", + 20: "5EYCAe5jLQhn6ofDSvvfwFRqHYNUXpyCgeomD6RdxWrxFpQR", + 21: "5EYCAe5jLQhn6ofDSvvwgGyRQ33fzP55RKkGm37URLjgXG7M", + 22: "5EYCAe5jLQhn6ofDSvwDRJX1WXisSwAx9zgnJyoJtAcQo59Y", + 23: "5EYCAe5jLQhn6ofDSvwVAL4bd2Q4uVGptfdHrvV9LzV94VBb", + 24: "5EYCAe5jLQhn6ofDSvwkuMcBjX5GN3NhdLZoQsAyopMsL7A7", + 25: "5EYCAe5jLQhn6ofDSvx2eP9mr1kTpbUaN1WJxorpGeEbbfgG", + 26: "5EYCAe5jLQhn6ofDSvxJPQhMxWRfH9aT6gSpWkYejU7KsbGp", + 27: "5EYCAe5jLQhn6ofDSvxa8SEx516rjhgKqMPL4hEVCHz49DPw", + 28: "5EYCAe5jLQhn6ofDSvxqsTnYBVn4CFnCa2KqcdvKf7rnQo7f", + 29: "5EYCAe5jLQhn6ofDSvy7cVL8HzTFeot5JhGMAacA7wjWgPix", + 30: "5EYCAe5jLQhn6ofDSvyPMWsiQV8T7Myx3NCriXHzamcEwyqa", + 31: "5EYCAe5jLQhn6ofDSvyf6YRJWyoeZv5pn39NGTyq3bUyDc8k", + 32: "5EYCAe5jLQhn6ofDSvyvqZxtdUUr2UBhWi5spQffWRMhV5hU", + 33: "5EYCAe5jLQhn6ofDSvzCabWUjyA3V2HaFP2PNMMVyFERkxPm", + 34: "5EYCAe5jLQhn6ofDSvzUKd44rTqEwaPSz3xtvJ3LS57A2Td3", + 35: "5EYCAe5jLQhn6ofDSvzk4ebexxWSQ8VKiiuQUEjAttytJ8Nx", + 36: "5EYCAe5jLQhn6ofDSw11og9F5TBdrgbCTPqv2BR1MircZp68", + 37: "5EYCAe5jLQhn6ofDSw1HYhgqBwrqKEh5C4nRa86qpYjLqCQd", + 38: "5EYCAe5jLQhn6ofDSw1ZHjERJSY2mnnwvjiw84ngHNc56t9n", + 39: "5EYCAe5jLQhn6ofDSw1q2kn1QwDEELtpfQfSg1UWkCUoNVFh", + 40: "5EYCAe5jLQhn6ofDSw26mnKbXRtRgtzhQ5bxDxAMD2MXeL6A", + 41: "5EYCAe5jLQhn6ofDSw2NWosBdvZd9T6a8kYTmtrBfrEFusmX", + 42: "5EYCAe5jLQhn6ofDSw2eFqQmkREpc1CSsRUyKqY28g6zBbxD", + 43: "5EYCAe5jLQhn6ofDSw2uzrxMruv24ZJKc6RUsnDrbVyiT4uZ", + 44: "5EYCAe5jLQhn6ofDSw3BjtVwyQbDX7QCLmMzRiuh4KrSienC", + 45: "5EYCAe5jLQhn6ofDSw3TUv3Y5uGQyfW55SJVyfbXX9jAzHBc", + 46: "5EYCAe5jLQhn6ofDSw3jDwb8CPwcSDbwp7F1XcHMyybuFsV6", + 47: "5EYCAe5jLQhn6ofDSw3zxy8iJtcotmhpYnBX5YyCSoUdXS9C", + 48: "5EYCAe5jLQhn6ofDSw4GhzgJRPJ1MKohHT82dVf2udMMo854", + 49: "5EYCAe5jLQhn6ofDSw4YT2DtXsyCosua284YBSLsNTE64sjn", + 50: "5EYCAe5jLQhn6ofDSw4pC3mUeNeQGS1Sko13jP2hqH6pLJc1", + 51: "5EYCAe5jLQhn6ofDSw55w5K4ksKbiz7KVTwZHKiYJ6yYc62p", + 52: "5EYCAe5jLQhn6ofDSw5Mg6resMzoBYDCE8t4qGQNkvrGsYLi", + 53: "5EYCAe5jLQhn6ofDSw5dR8QEyrfze6K4xopaPD6DDkj19BcH", + 54: "5EYCAe5jLQhn6ofDSw5uA9wq6MMC6eQwhUm5w9n3gabjR243", + 55: "5EYCAe5jLQhn6ofDSw6AuBVRCr2PZCWpS9hbV6Tt9QUTghER", + 56: "5EYCAe5jLQhn6ofDSw6SeD31KLhb1kchApe7339icEMBxKr7", + 57: "5EYCAe5jLQhn6ofDSw6iPEabRqNnUJiZuVacayqZ54DvDhGB", + 58: "5EYCAe5jLQhn6ofDSw6z8G8BYL3yvrpSeAX88vXPXt6eVRoY", + 59: "5EYCAe5jLQhn6ofDSw7FsHfmepjBPQvKNqTdgsDDzhyNky3e", + 60: "5EYCAe5jLQhn6ofDSw7XcKDMmKQNqy2C7WQ9Eou4TXr72f1B", + 61: "5EYCAe5jLQhn6ofDSw7oMLkwsp5aJX84rBLenkatvMiqJC2W", + 62: "5EYCAe5jLQhn6ofDSw856NJXzJkmm5DwarHALhGjPBbZa5wW", + 63: "5EYCAe5jLQhn6ofDSw8LqPr86oRyDdKpKXDftdxZr1UHqWzq", + 64: "5EYCAe5jLQhn6ofDSw8caRPiDJ7AgBRh4CABSaeQJqM278gq", + 65: "5EYCAe5jLQhn6ofDSw8tKSwJKnnN8jXZns6gzXLEmfDkNtXu", + 66: "5EYCAe5jLQhn6ofDSw9A4UUtSHTZbHdSXY3CYU25EV6UeLH2", + 67: "5EYCAe5jLQhn6ofDSw9RoW2UYn8m3qjKGCyi6QhuhJyCv9nu", + 68: "5EYCAe5jLQhn6ofDSw9hYXa4fGoxWPqBzsvDeMPkA8qwBecQ", + 69: "5EYCAe5jLQhn6ofDSw9yHZ7emmV9xww4jYrjCJ5acxifTH7b", + 70: "5EYCAe5jLQhn6ofDSwAF2afEtGAMRW2wUDoEkEmR5nbPiuFf", + 71: "5EYCAe5jLQhn6ofDSwAWmcCpzkqYt48pCtjkJBTFYcU7ziWG", + 72: "5EYCAe5jLQhn6ofDSwAnWdkR7FWkLcEgwZgFr8961SLrGPJp", + 73: "5EYCAe5jLQhn6ofDSwB4FfJ1DkBwoALZgEcmQ4pvUGDaXxGw", + 74: "5EYCAe5jLQhn6ofDSwBKzgqbLEs9FiSSQuZGx1Wkw66JoNQY", + 75: "5EYCAe5jLQhn6ofDSwBbjiPBSjYLiGYK9aVnVxCbPuy357eQ", + 76: "5EYCAe5jLQhn6ofDSwBsUjvmZEDYApeBtFSJ3ttRrjqmLmRP", + 77: "5EYCAe5jLQhn6ofDSwC9DmUMfitjdNk4cvNobqaGKZiVcSd4", + 78: "5EYCAe5jLQhn6ofDSwCQxo1wnDZw5vqwMbKK9nG6nPbDsr3v", + 79: "5EYCAe5jLQhn6ofDSwCghpZXtiF8YUwp6GFphiwwFDTx9ZXw", + 80: "5EYCAe5jLQhn6ofDSwCxSr781CvL133gpwCLFfdmi3LgRGUs", + 81: "5EYCAe5jLQhn6ofDSwDEBsei7hbXTb9ZZc8qocKcAsDQgmDH", + 82: "5EYCAe5jLQhn6ofDSwDVvuCJECGiv9FSJH5MMZ1Sdh68xe6G", + 83: "5EYCAe5jLQhn6ofDSwDmfvjtLgwvNhMK2x1ruVhH6WxsE2Rh", + 84: "5EYCAe5jLQhn6ofDSwE3QxHUTBd7qFTBmcxNTSP7ZLqbVqHX", + 85: "5EYCAe5jLQhn6ofDSwEK9yq4ZgJKHoZ4WHtt1P4x2AiKmP2V", + 86: "5EYCAe5jLQhn6ofDSwEau1NegAyWkMewExqPZKknUzb42r36", + 87: "5EYCAe5jLQhn6ofDSwEre2vEnfeiCukoydmu7GScwpTnJa5d", + 88: "5EYCAe5jLQhn6ofDSwF8P4TpuAKufTrgiJiQfD8TQeLWaGop", + 89: "5EYCAe5jLQhn6ofDSwFQ861R1f1781xZSyevD9pHsUDEqiBR", + 90: "5EYCAe5jLQhn6ofDSwFfs7Z189gJaa4SBebRm6W8LJ5y7dfH", + 91: "5EYCAe5jLQhn6ofDSwFwc96bEeMW38AJvKXwK3Bxo7xhP3yn", + 92: "5EYCAe5jLQhn6ofDSwGDMAeBM92hVgGBezUSrysoFwqReqrS", + 93: "5EYCAe5jLQhn6ofDSwGV6CBmTdhtxEN4PfQxQvZdimi9vW9r", + 94: "5EYCAe5jLQhn6ofDSwGkqDjMa8P6QnTw8LMTxsFUBbatC8C5", + 95: "5EYCAe5jLQhn6ofDSwH2aFGwgd4HsLZos1HyWowJeRTcTVsg", + 96: "5EYCAe5jLQhn6ofDSwHJKGpXo7jVKtfgbgEV4kd97FLLjBeJ", + 97: "5EYCAe5jLQhn6ofDSwHa4JN7ucQgnSmZLMAzchJya5D4zq8v", + 98: "5EYCAe5jLQhn6ofDSwHqoKui275tEzsS527WAdzp2u5oGNSd", + 99: "5EYCAe5jLQhn6ofDSwJ7YMTJ8bm5hYyJoh41iageVixXYH59", + 100: "5EYCAe5jLQhn6ofDSwJPHNztF6SHA75BYMzXGXNUxYqFoj9g", + 101: "5EYCAe5jLQhn6ofDSwJf2QYUMb7UcfB4H2w2pU4KRNhz5GP5", + 102: "5EYCAe5jLQhn6ofDSwJvmS64U5ng5DGw1hsYNQk9tCaiLvoS", + 103: "5EYCAe5jLQhn6ofDSwKCWTdeaaTsXmNokNp3vMRzM2TScknA", + 104: "5EYCAe5jLQhn6ofDSwKUFVBEh594zKUgV3kZUJ7porLAtE76", + 105: "5EYCAe5jLQhn6ofDSwKjzWipoZpGSsaZDih52EofGgCu9mbP", + 106: "5EYCAe5jLQhn6ofDSwL1jYGQv4VTuRgRxPdaaBVVjW5dRU9u", + 107: "5EYCAe5jLQhn6ofDSwLHUZp12ZAfMynJh4a688BLCKxMhEMq", + 108: "5EYCAe5jLQhn6ofDSwLZDbMb93qrpXtBRjWbg4sAf9q5xtB8", + 109: "5EYCAe5jLQhn6ofDSwLpxcuBFYX4H5z4AQT7E1Z17yhpELLK", + 110: "5EYCAe5jLQhn6ofDSwM6heSmN3CFje5vu5PcmxEqaoaYW1KP", + 111: "5EYCAe5jLQhn6ofDSwMNSfzMUXsTCCBodkL8Ktvg3dTGmYbX", + 112: "5EYCAe5jLQhn6ofDSwMeBhXwb2YeekHgNRGdsqcWWTL13NLP", + 113: "5EYCAe5jLQhn6ofDSwMuvj5XhXDr7JPZ76D9RnJLyHCjK2Zy", + 114: "5EYCAe5jLQhn6ofDSwNBfkd7p1u3ZrVRqm9eyizBS75TaPgK", + 115: "5EYCAe5jLQhn6ofDSwNTQnAhvWaF2QbJaS6AXfg1tvxBrDUN", + 116: "5EYCAe5jLQhn6ofDSwNj9oiJ31FSUxhBK72g5cMrMkpv7iJx", + 117: "5EYCAe5jLQhn6ofDSwNztqFt9VvdwWo43myBdZ3gpahePQpf", + 118: "5EYCAe5jLQhn6ofDSwPGdroUFzbqQ4tvnSuhBVjXHQaNet2o", + 119: "5EYCAe5jLQhn6ofDSwPYNtM4NVH2rczoX7rCjSRMkET6vioH", + 120: "5EYCAe5jLQhn6ofDSwPp7uteUyxEKB6gFnniHP7CD4KqCQDN", + 121: "5EYCAe5jLQhn6ofDSwQ5rwSEbUdRmjCYzTjDqKo2ftCZTubr", + 122: "5EYCAe5jLQhn6ofDSwQMbxyphyJdEHJRj8fjPGUs8i5HjcA3", + 123: "5EYCAe5jLQhn6ofDSwQdLzXQpTypgqQJTocEwDAhbXx21Awy", + 124: "5EYCAe5jLQhn6ofDSwQu624zvxf29PWBCUYkV9rY4MpkGu1f", + 125: "5EYCAe5jLQhn6ofDSwRAq3cb3TLDbwc3w9VG36YNXBhUYKDi", + 126: "5EYCAe5jLQhn6ofDSwRSa5AB9x1R4VhvfpRmb3ECz1aCp2ze", + 127: "5EYCAe5jLQhn6ofDSwRiK6hmGSgcX3ooQVNH8yv3SqSw5mpH", + 128: "5EYCAe5jLQhn6ofDSwRz48FMNwMoybug9AJngvbsufKfME2t", + } + + return NETUID_TO_ACCOUNT_ID[netuid]; +} export async function getStake(api: TypedApi, hotkey: string, coldkey: string, netuid: number): Promise { const value = (await api.query.SubtensorModule.AlphaV2.getValue(hotkey, coldkey, netuid)); diff --git a/docs/subnet_account_ids.md b/docs/subnet_account_ids.md new file mode 100644 index 0000000000..a3fc180548 --- /dev/null +++ b/docs/subnet_account_ids.md @@ -0,0 +1,1029 @@ +# The subnet account IDs + +netuid: ss58 account ID + +0: 5EYCAe5jLQhn6ofDSvqF6iY53erXNkwhyE1aCEgvi1NNs91F +1: 5EYCAe5jLQhn6ofDSvqWqk5fA9XiqK3ahtx5kBNmAqF78mqL +2: 5EYCAe5jLQhn6ofDSvqnamdFGeCvHs9TSZtbJ84bdf7qQRc6 +3: 5EYCAe5jLQhn6ofDSvr4KoAqP8t7kRFLBEq6r4kS6UzZgCb5 +4: 5EYCAe5jLQhn6ofDSvrL4piRVdZKCyMCuumcQ1SGZJsHwmeE +5: 5EYCAe5jLQhn6ofDSvrborG1c8EWfXT5eai7wx8728k2DHK7 +6: 5EYCAe5jLQhn6ofDSvrsYsobicui85YxPFedVtowUxckUuF8 +7: 5EYCAe5jLQhn6ofDSvs9HuMBq7auadeq7vb93qVmwnVUkg5A +8: 5EYCAe5jLQhn6ofDSvsR2vtmwcG73BkhrbXebnBcQcND2Bdh +9: 5EYCAe5jLQhn6ofDSvsgmxSN46wJVjrabGUA9isSsSEwHnFy +10: 5EYCAe5jLQhn6ofDSvsxWyyxAbcVxHxTKwQfhfZHLG7fZUJG +11: 5EYCAe5jLQhn6ofDSvtEG1XYH6HhQr4L4cMBFcF7o5zPpyA3 +12: 5EYCAe5jLQhn6ofDSvtW1358PaxtsQACoHHgoYvxFus86kJK +13: 5EYCAe5jLQhn6ofDSvtmk4ciW5e6KxG5XxECMVcnijjrN8rz +14: 5EYCAe5jLQhn6ofDSvu3V6AJcaKHnWMxGdAhuSJdBZcadwDn +15: 5EYCAe5jLQhn6ofDSvuKE7htj4zVF4Tq1J7DTNzTePVJucfX +16: 5EYCAe5jLQhn6ofDSvuay9FUqZfghcZhjy3j1KgJ7DN3BDc2 +17: 5EYCAe5jLQhn6ofDSvuriAo4x4LtAAfaUdzEZGN8a3EmSncG +18: 5EYCAe5jLQhn6ofDSvv8TCLf4Z25cimTDJvk7D3y2s7ViZEm +19: 5EYCAe5jLQhn6ofDSvvQCDtFB3hH5GsKwysFf9joVgzDytnb +20: 5EYCAe5jLQhn6ofDSvvfwFRqHYNUXpyCgeomD6RdxWrxFpQR +21: 5EYCAe5jLQhn6ofDSvvwgGyRQ33fzP55RKkGm37URLjgXG7M +22: 5EYCAe5jLQhn6ofDSvwDRJX1WXisSwAx9zgnJyoJtAcQo59Y +23: 5EYCAe5jLQhn6ofDSvwVAL4bd2Q4uVGptfdHrvV9LzV94VBb +24: 5EYCAe5jLQhn6ofDSvwkuMcBjX5GN3NhdLZoQsAyopMsL7A7 +25: 5EYCAe5jLQhn6ofDSvx2eP9mr1kTpbUaN1WJxorpGeEbbfgG +26: 5EYCAe5jLQhn6ofDSvxJPQhMxWRfH9aT6gSpWkYejU7KsbGp +27: 5EYCAe5jLQhn6ofDSvxa8SEx516rjhgKqMPL4hEVCHz49DPw +28: 5EYCAe5jLQhn6ofDSvxqsTnYBVn4CFnCa2KqcdvKf7rnQo7f +29: 5EYCAe5jLQhn6ofDSvy7cVL8HzTFeot5JhGMAacA7wjWgPix +30: 5EYCAe5jLQhn6ofDSvyPMWsiQV8T7Myx3NCriXHzamcEwyqa +31: 5EYCAe5jLQhn6ofDSvyf6YRJWyoeZv5pn39NGTyq3bUyDc8k +32: 5EYCAe5jLQhn6ofDSvyvqZxtdUUr2UBhWi5spQffWRMhV5hU +33: 5EYCAe5jLQhn6ofDSvzCabWUjyA3V2HaFP2PNMMVyFERkxPm +34: 5EYCAe5jLQhn6ofDSvzUKd44rTqEwaPSz3xtvJ3LS57A2Td3 +35: 5EYCAe5jLQhn6ofDSvzk4ebexxWSQ8VKiiuQUEjAttytJ8Nx +36: 5EYCAe5jLQhn6ofDSw11og9F5TBdrgbCTPqv2BR1MircZp68 +37: 5EYCAe5jLQhn6ofDSw1HYhgqBwrqKEh5C4nRa86qpYjLqCQd +38: 5EYCAe5jLQhn6ofDSw1ZHjERJSY2mnnwvjiw84ngHNc56t9n +39: 5EYCAe5jLQhn6ofDSw1q2kn1QwDEELtpfQfSg1UWkCUoNVFh +40: 5EYCAe5jLQhn6ofDSw26mnKbXRtRgtzhQ5bxDxAMD2MXeL6A +41: 5EYCAe5jLQhn6ofDSw2NWosBdvZd9T6a8kYTmtrBfrEFusmX +42: 5EYCAe5jLQhn6ofDSw2eFqQmkREpc1CSsRUyKqY28g6zBbxD +43: 5EYCAe5jLQhn6ofDSw2uzrxMruv24ZJKc6RUsnDrbVyiT4uZ +44: 5EYCAe5jLQhn6ofDSw3BjtVwyQbDX7QCLmMzRiuh4KrSienC +45: 5EYCAe5jLQhn6ofDSw3TUv3Y5uGQyfW55SJVyfbXX9jAzHBc +46: 5EYCAe5jLQhn6ofDSw3jDwb8CPwcSDbwp7F1XcHMyybuFsV6 +47: 5EYCAe5jLQhn6ofDSw3zxy8iJtcotmhpYnBX5YyCSoUdXS9C +48: 5EYCAe5jLQhn6ofDSw4GhzgJRPJ1MKohHT82dVf2udMMo854 +49: 5EYCAe5jLQhn6ofDSw4YT2DtXsyCosua284YBSLsNTE64sjn +50: 5EYCAe5jLQhn6ofDSw4pC3mUeNeQGS1Sko13jP2hqH6pLJc1 +51: 5EYCAe5jLQhn6ofDSw55w5K4ksKbiz7KVTwZHKiYJ6yYc62p +52: 5EYCAe5jLQhn6ofDSw5Mg6resMzoBYDCE8t4qGQNkvrGsYLi +53: 5EYCAe5jLQhn6ofDSw5dR8QEyrfze6K4xopaPD6DDkj19BcH +54: 5EYCAe5jLQhn6ofDSw5uA9wq6MMC6eQwhUm5w9n3gabjR243 +55: 5EYCAe5jLQhn6ofDSw6AuBVRCr2PZCWpS9hbV6Tt9QUTghER +56: 5EYCAe5jLQhn6ofDSw6SeD31KLhb1kchApe7339icEMBxKr7 +57: 5EYCAe5jLQhn6ofDSw6iPEabRqNnUJiZuVacayqZ54DvDhGB +58: 5EYCAe5jLQhn6ofDSw6z8G8BYL3yvrpSeAX88vXPXt6eVRoY +59: 5EYCAe5jLQhn6ofDSw7FsHfmepjBPQvKNqTdgsDDzhyNky3e +60: 5EYCAe5jLQhn6ofDSw7XcKDMmKQNqy2C7WQ9Eou4TXr72f1B +61: 5EYCAe5jLQhn6ofDSw7oMLkwsp5aJX84rBLenkatvMiqJC2W +62: 5EYCAe5jLQhn6ofDSw856NJXzJkmm5DwarHALhGjPBbZa5wW +63: 5EYCAe5jLQhn6ofDSw8LqPr86oRyDdKpKXDftdxZr1UHqWzq +64: 5EYCAe5jLQhn6ofDSw8caRPiDJ7AgBRh4CABSaeQJqM278gq +65: 5EYCAe5jLQhn6ofDSw8tKSwJKnnN8jXZns6gzXLEmfDkNtXu +66: 5EYCAe5jLQhn6ofDSw9A4UUtSHTZbHdSXY3CYU25EV6UeLH2 +67: 5EYCAe5jLQhn6ofDSw9RoW2UYn8m3qjKGCyi6QhuhJyCv9nu +68: 5EYCAe5jLQhn6ofDSw9hYXa4fGoxWPqBzsvDeMPkA8qwBecQ +69: 5EYCAe5jLQhn6ofDSw9yHZ7emmV9xww4jYrjCJ5acxifTH7b +70: 5EYCAe5jLQhn6ofDSwAF2afEtGAMRW2wUDoEkEmR5nbPiuFf +71: 5EYCAe5jLQhn6ofDSwAWmcCpzkqYt48pCtjkJBTFYcU7ziWG +72: 5EYCAe5jLQhn6ofDSwAnWdkR7FWkLcEgwZgFr8961SLrGPJp +73: 5EYCAe5jLQhn6ofDSwB4FfJ1DkBwoALZgEcmQ4pvUGDaXxGw +74: 5EYCAe5jLQhn6ofDSwBKzgqbLEs9FiSSQuZGx1Wkw66JoNQY +75: 5EYCAe5jLQhn6ofDSwBbjiPBSjYLiGYK9aVnVxCbPuy357eQ +76: 5EYCAe5jLQhn6ofDSwBsUjvmZEDYApeBtFSJ3ttRrjqmLmRP +77: 5EYCAe5jLQhn6ofDSwC9DmUMfitjdNk4cvNobqaGKZiVcSd4 +78: 5EYCAe5jLQhn6ofDSwCQxo1wnDZw5vqwMbKK9nG6nPbDsr3v +79: 5EYCAe5jLQhn6ofDSwCghpZXtiF8YUwp6GFphiwwFDTx9ZXw +80: 5EYCAe5jLQhn6ofDSwCxSr781CvL133gpwCLFfdmi3LgRGUs +81: 5EYCAe5jLQhn6ofDSwDEBsei7hbXTb9ZZc8qocKcAsDQgmDH +82: 5EYCAe5jLQhn6ofDSwDVvuCJECGiv9FSJH5MMZ1Sdh68xe6G +83: 5EYCAe5jLQhn6ofDSwDmfvjtLgwvNhMK2x1ruVhH6WxsE2Rh +84: 5EYCAe5jLQhn6ofDSwE3QxHUTBd7qFTBmcxNTSP7ZLqbVqHX +85: 5EYCAe5jLQhn6ofDSwEK9yq4ZgJKHoZ4WHtt1P4x2AiKmP2V +86: 5EYCAe5jLQhn6ofDSwEau1NegAyWkMewExqPZKknUzb42r36 +87: 5EYCAe5jLQhn6ofDSwEre2vEnfeiCukoydmu7GScwpTnJa5d +88: 5EYCAe5jLQhn6ofDSwF8P4TpuAKufTrgiJiQfD8TQeLWaGop +89: 5EYCAe5jLQhn6ofDSwFQ861R1f1781xZSyevD9pHsUDEqiBR +90: 5EYCAe5jLQhn6ofDSwFfs7Z189gJaa4SBebRm6W8LJ5y7dfH +91: 5EYCAe5jLQhn6ofDSwFwc96bEeMW38AJvKXwK3Bxo7xhP3yn +92: 5EYCAe5jLQhn6ofDSwGDMAeBM92hVgGBezUSrysoFwqReqrS +93: 5EYCAe5jLQhn6ofDSwGV6CBmTdhtxEN4PfQxQvZdimi9vW9r +94: 5EYCAe5jLQhn6ofDSwGkqDjMa8P6QnTw8LMTxsFUBbatC8C5 +95: 5EYCAe5jLQhn6ofDSwH2aFGwgd4HsLZos1HyWowJeRTcTVsg +96: 5EYCAe5jLQhn6ofDSwHJKGpXo7jVKtfgbgEV4kd97FLLjBeJ +97: 5EYCAe5jLQhn6ofDSwHa4JN7ucQgnSmZLMAzchJya5D4zq8v +98: 5EYCAe5jLQhn6ofDSwHqoKui275tEzsS527WAdzp2u5oGNSd +99: 5EYCAe5jLQhn6ofDSwJ7YMTJ8bm5hYyJoh41iageVixXYH59 +100: 5EYCAe5jLQhn6ofDSwJPHNztF6SHA75BYMzXGXNUxYqFoj9g +101: 5EYCAe5jLQhn6ofDSwJf2QYUMb7UcfB4H2w2pU4KRNhz5GP5 +102: 5EYCAe5jLQhn6ofDSwJvmS64U5ng5DGw1hsYNQk9tCaiLvoS +103: 5EYCAe5jLQhn6ofDSwKCWTdeaaTsXmNokNp3vMRzM2TScknA +104: 5EYCAe5jLQhn6ofDSwKUFVBEh594zKUgV3kZUJ7porLAtE76 +105: 5EYCAe5jLQhn6ofDSwKjzWipoZpGSsaZDih52EofGgCu9mbP +106: 5EYCAe5jLQhn6ofDSwL1jYGQv4VTuRgRxPdaaBVVjW5dRU9u +107: 5EYCAe5jLQhn6ofDSwLHUZp12ZAfMynJh4a688BLCKxMhEMq +108: 5EYCAe5jLQhn6ofDSwLZDbMb93qrpXtBRjWbg4sAf9q5xtB8 +109: 5EYCAe5jLQhn6ofDSwLpxcuBFYX4H5z4AQT7E1Z17yhpELLK +110: 5EYCAe5jLQhn6ofDSwM6heSmN3CFje5vu5PcmxEqaoaYW1KP +111: 5EYCAe5jLQhn6ofDSwMNSfzMUXsTCCBodkL8Ktvg3dTGmYbX +112: 5EYCAe5jLQhn6ofDSwMeBhXwb2YeekHgNRGdsqcWWTL13NLP +113: 5EYCAe5jLQhn6ofDSwMuvj5XhXDr7JPZ76D9RnJLyHCjK2Zy +114: 5EYCAe5jLQhn6ofDSwNBfkd7p1u3ZrVRqm9eyizBS75TaPgK +115: 5EYCAe5jLQhn6ofDSwNTQnAhvWaF2QbJaS6AXfg1tvxBrDUN +116: 5EYCAe5jLQhn6ofDSwNj9oiJ31FSUxhBK72g5cMrMkpv7iJx +117: 5EYCAe5jLQhn6ofDSwNztqFt9VvdwWo43myBdZ3gpahePQpf +118: 5EYCAe5jLQhn6ofDSwPGdroUFzbqQ4tvnSuhBVjXHQaNet2o +119: 5EYCAe5jLQhn6ofDSwPYNtM4NVH2rczoX7rCjSRMkET6vioH +120: 5EYCAe5jLQhn6ofDSwPp7uteUyxEKB6gFnniHP7CD4KqCQDN +121: 5EYCAe5jLQhn6ofDSwQ5rwSEbUdRmjCYzTjDqKo2ftCZTubr +122: 5EYCAe5jLQhn6ofDSwQMbxyphyJdEHJRj8fjPGUs8i5HjcA3 +123: 5EYCAe5jLQhn6ofDSwQdLzXQpTypgqQJTocEwDAhbXx21Awy +124: 5EYCAe5jLQhn6ofDSwQu624zvxf29PWBCUYkV9rY4MpkGu1f +125: 5EYCAe5jLQhn6ofDSwRAq3cb3TLDbwc3w9VG36YNXBhUYKDi +126: 5EYCAe5jLQhn6ofDSwRSa5AB9x1R4VhvfpRmb3ECz1aCp2ze +127: 5EYCAe5jLQhn6ofDSwRiK6hmGSgcX3ooQVNH8yv3SqSw5mpH +128: 5EYCAe5jLQhn6ofDSwRz48FMNwMoybug9AJngvbsufKfME2t +129: 5EYCAe5jLQhn6ofDSwSFo9nwVS31SA1YsqFJEsHiNVCPcuZ9 +130: 5EYCAe5jLQhn6ofDSwSXYBLXbviCti7RcWBonoyYqK57tgCT +131: 5EYCAe5jLQhn6ofDSwSoHCt7iRPQMGDJMB8KLkfPJ8wrAGyP +132: 5EYCAe5jLQhn6ofDSwT52ERhpv4bopKB5r4pthMDkxpaRs97 +133: 5EYCAe5jLQhn6ofDSwTLmFyHwQjoGNR3pX1LSe34DnhJhU9A +134: 5EYCAe5jLQhn6ofDSwTcWHWt3uQzivWvZBwqzaitgca2xvCA +135: 5EYCAe5jLQhn6ofDSwTtFK4UAQ6CBUcoHrtMYXQj9SSmEgDM +136: 5EYCAe5jLQhn6ofDSwU9zLc4GtmPe2ig2Xps6U6ZcGKVWLNs +137: 5EYCAe5jLQhn6ofDSwURjN9ePPSb6apYmCmNeQnQ56CDn1SN +138: 5EYCAe5jLQhn6ofDSwUhUPhEVt7nZ8vRVshtCMUEXv4x3U6G +139: 5EYCAe5jLQhn6ofDSwUyDREpcNnz1h2JEYePkJA4zjwgK8dv +140: 5EYCAe5jLQhn6ofDSwVExSnQisUBUF8AyDauJEquTZpQaoue +141: 5EYCAe5jLQhn6ofDSwVWhUKzqN9NvoE3htXQrBXjvPh8rQgX +142: 5EYCAe5jLQhn6ofDSwVnSVsawrpaPMKvSZTvQ8DaPDZs8C7o +143: 5EYCAe5jLQhn6ofDSwW4BXRB4MVmquRoBEQRx4uQr3SbPfUD +144: 5EYCAe5jLQhn6ofDSwWKvYxmArAyJTXfuuLwW1bFJsKKf8Ax +145: 5EYCAe5jLQhn6ofDSwWbfaWMHLrAm1dYeaHT3xH5mhC3vmAe +146: 5EYCAe5jLQhn6ofDSwWsQc3wPqXNDZjRPFDxbtxvEX4nCgWj +147: 5EYCAe5jLQhn6ofDSwX99dbXWLCZg7qJ7vAU9qekhLwWUAUr +148: 5EYCAe5jLQhn6ofDSwXQtf97cpsm8fwArb6yhnLbAApEjeXz +149: 5EYCAe5jLQhn6ofDSwXgdgghjKYxbE33bG3VFj2Rczgy1Vmr +150: 5EYCAe5jLQhn6ofDSwXxNiEHqpEA3n8vKvyzofiG5pZhGuX1 +151: 5EYCAe5jLQhn6ofDSwYE7jmsxJuMWLEo4bvWMcQ6YeSRYYra +152: 5EYCAe5jLQhn6ofDSwYVrmKU4oaYxtLfoGs1uZ5w1UK9pR2x +153: 5EYCAe5jLQhn6ofDSwYmbns4BJFkRSSYXwoXTVmmUJBt5u26 +154: 5EYCAe5jLQhn6ofDSwZ3LpQeHnvwszYRGck31STbw84cMhaR +155: 5EYCAe5jLQhn6ofDSwZK5qxEQHc9LYeJ1HgYZP9SPwwLdHWw +156: 5EYCAe5jLQhn6ofDSwZapsVpWnHLo6kAjxd47KqGrmp4tuDS +157: 5EYCAe5jLQhn6ofDSwZrZu3QdGxYFer3UdZZfGX7KbgoAWJ3 +158: 5EYCAe5jLQhn6ofDSwa8JvazjmdjiCwvDJW5DDCwnRZXRvL1 +159: 5EYCAe5jLQhn6ofDSwaQ3x8arGJwAm3nwySam9tnFFSFhYDW +160: 5EYCAe5jLQhn6ofDSwafnygAxkz8dK9fgeP6K6aci5JyyTiu +161: 5EYCAe5jLQhn6ofDSwawY1Dm5FfL5sFYRKKbs3GTAuBiEuDo +162: 5EYCAe5jLQhn6ofDSwbDH2mMBkLXYRMR9zG7QyxHdj4SWa3R +163: 5EYCAe5jLQhn6ofDSwbV24JwJF1izyTHtfCcxve86YwAnHW1 +164: 5EYCAe5jLQhn6ofDSwbkm5rXQjgvTXZAdL98WsKxZNou3ejC +165: 5EYCAe5jLQhn6ofDSwc2W7Q7XEN7v5f3N15e4p1o2CgdKWRW +166: 5EYCAe5jLQhn6ofDSwcJF8whdj3KNdkv6g29ckhdV2ZMbAew +167: 5EYCAe5jLQhn6ofDSwcZzAVHkDiWqBrnqLxfAhPTwrS5rhzb +168: 5EYCAe5jLQhn6ofDSwcqjC2sriPiHjxfa1uAie5JQgJp8CWe +169: 5EYCAe5jLQhn6ofDSwd7UDaTyD4ukJ4YJgqgGam8sWBYQ2H8 +170: 5EYCAe5jLQhn6ofDSwdPDF845hk7CrAR3MnBpXSyLL4GfbVT +171: 5EYCAe5jLQhn6ofDSwdexGfeCCRJfQGHn2ihNU8oo9vzw6s9 +172: 5EYCAe5jLQhn6ofDSwdvhJDEJh6W7xNAWhfCvQpeFyojCkDK +173: 5EYCAe5jLQhn6ofDSweCSKkpRBmhaWU3FNbiUMWUiogTUUax +174: 5EYCAe5jLQhn6ofDSweUBMJQXgSu34Zuz3YE2JCKBdZBjxx9 +175: 5EYCAe5jLQhn6ofDSwejvNqzeB86VcfniiUjaEt9eTRv1hEQ +176: 5EYCAe5jLQhn6ofDSwf1fQPakfoHxAmfTPRF8BZz7HJeHEFa +177: 5EYCAe5jLQhn6ofDSwfHQRwAsAUVQisYC4Mkg8Fpa7BNZ735 +178: 5EYCAe5jLQhn6ofDSwfZ9TUkyf9gsGyQvjJGE4wf2w46pjEb +179: 5EYCAe5jLQhn6ofDSwfptV2M69ptKq5HfQEmn1dVVkvq6Jdm +180: 5EYCAe5jLQhn6ofDSwg6dWZwCeW5nPBAQ5BHKxKKxaoZMqLc +181: 5EYCAe5jLQhn6ofDSwgNNY7XK9BHEwH38k7nsu1ARQgHdMC3 +182: 5EYCAe5jLQhn6ofDSwge7Zf7RdrUhVNusR4JRqgztEZ1uEhR +183: 5EYCAe5jLQhn6ofDSwgurbChY8XgA3Unc5zoynNqM4RkAppF +184: 5EYCAe5jLQhn6ofDSwhBbckHedCscbafLkwKXj4fotJUSCzn +185: 5EYCAe5jLQhn6ofDSwhTLeHsm7t559gY5Rsq5fkWGiBChwy2 +186: 5EYCAe5jLQhn6ofDSwhj5fqTscZGXhnQp6pLdcSLjY3vyjeX +187: 5EYCAe5jLQhn6ofDSwhzphP3z7ETzFtHYmkrBZ8BCMvfFF73 +188: 5EYCAe5jLQhn6ofDSwiGZive6bufSozAHShMjVp1fBoPWsGG +189: 5EYCAe5jLQhn6ofDSwiYJkUED6aruN6327dsHSVr81g7nZdr +190: 5EYCAe5jLQhn6ofDSwip3n1pKbG4MvBuknaNqPBgaqYr4Epy +191: 5EYCAe5jLQhn6ofDSwj5noZQS5wFpUHnVTWtPKsX3fRaKfPX +192: 5EYCAe5jLQhn6ofDSwjMXq6zYacTH2PfE8TPwGZMWVJJbVUj +193: 5EYCAe5jLQhn6ofDSwjdGreaf5HejaVXxoPuVDFByKB2ryMD +194: 5EYCAe5jLQhn6ofDSwju1tCAmZxrC8bQhULR39w2S93m8YwD +195: 5EYCAe5jLQhn6ofDSwkAkujkt4e3eghHS9Gvb6crtxvVQ8TS +196: 5EYCAe5jLQhn6ofDSwkSVwHLzZKF7EoAApDS93JhMnoDfqYs +197: 5EYCAe5jLQhn6ofDSwkiExpw73zSZnu2uV9wgyzXpcfwwNtd +198: 5EYCAe5jLQhn6ofDSwkyyzNXDYfe2LzueA6TEvgNHSYgD9fh +199: 5EYCAe5jLQhn6ofDSwmFj1v7L3LqUu6nNq2xnsNCkGRQUdiJ +200: 5EYCAe5jLQhn6ofDSwmXU3ThSY22wTCf7VyULp43D6J8kSnP +201: 5EYCAe5jLQhn6ofDSwmoD51HZ2hEQ1JXrAuytkjsfvAs217d +202: 5EYCAe5jLQhn6ofDSwn4x6YsfXNRrZQQaqrVShRi8k3bHTHJ +203: 5EYCAe5jLQhn6ofDSwnLh86Tn23dK7WHKWnzze7YbZvKZ9W4 +204: 5EYCAe5jLQhn6ofDSwncS9e3tWipmfcA4BjWYaoP4Po3ptFu +205: 5EYCAe5jLQhn6ofDSwntBBBe11Q2EDi2nrg26XVDXDfn6UvC +206: 5EYCAe5jLQhn6ofDSwo9vCjE7W5DgmouXXcXeUB3z3YWN5rH +207: 5EYCAe5jLQhn6ofDSwoRfEGpDzkR9KunGCZ3CQrtSsREdeTi +208: 5EYCAe5jLQhn6ofDSwohQFpQLVRcbt1ezsVYkMYiuhHxuG9h +209: 5EYCAe5jLQhn6ofDSwoy9HMzSz6p4S7XjYS4JJEZNXAhB57Z +210: 5EYCAe5jLQhn6ofDSwpEtJuaZUn1WzDQUDNZrEvPqM3RShVi +211: 5EYCAe5jLQhn6ofDSwpWdLTAfyTCyYKHCtK5QBcEJAv9i5ua +212: 5EYCAe5jLQhn6ofDSwpnNMzknU8QS6R9wZFax8J4kznsyjCK +213: 5EYCAe5jLQhn6ofDSwq47PYLtxobteX2gEC6W4yuDpfcFKAe +214: 5EYCAe5jLQhn6ofDSwqKrR5w1TUoMCcuQu8c41fjgeYLXFWn +215: 5EYCAe5jLQhn6ofDSwqbbSdX7x9zokin9a57bxMa9UR4nnKt +216: 5EYCAe5jLQhn6ofDSwqsLUB7ESqCGJpetF1d9u3QcJHo4J89 +217: 5EYCAe5jLQhn6ofDSwr95VihLwWPirvXcux8hqjF58AXKq2x +218: 5EYCAe5jLQhn6ofDSwrQpXGHTSBbBR2QMateFnR5Xx3Fbkd6 +219: 5EYCAe5jLQhn6ofDSwrgZYosZvrndy8H6Fq9oj6uzmuys6og +220: 5EYCAe5jLQhn6ofDSwrxJaMTgRXz6XE9pvmfMfnkTbni8r8h +221: 5EYCAe5jLQhn6ofDSwsE3bu3nvDBZ5L2ZbiAucUavRfSQWNT +222: 5EYCAe5jLQhn6ofDSwsVndSduQtP1dRuJGegTZARPFYAg3e9 +223: 5EYCAe5jLQhn6ofDSwsmXezE1uZaUBXn2wbC1VrFr5QtwtdM +224: 5EYCAe5jLQhn6ofDSwt3GgXp8QEmvjdemcXhZSY6JuHdDNAJ +225: 5EYCAe5jLQhn6ofDSwtK1i5QEtuyPHjXWHUD7PDvmjAMUpH7 +226: 5EYCAe5jLQhn6ofDSwtakjczMPbAqqqQExQifKumEZ35kYLM +227: 5EYCAe5jLQhn6ofDSwtrVmAaTtGNJPwGydMEDGbbhNup2Aem +228: 5EYCAe5jLQhn6ofDSwu8EniAaNwZkx39iJHjmDHSACnYHqVA +229: 5EYCAe5jLQhn6ofDSwuPypFkgscmDW92SyEFK9yGd2fGZP4J +230: 5EYCAe5jLQhn6ofDSwufiqoLoNHxg4EuBeAks6f75rXzqFTr +231: 5EYCAe5jLQhn6ofDSwuwTsLvuryA8cLmvK7GR3LwYgQj6f8r +232: 5EYCAe5jLQhn6ofDSwvDCttX2MeMbASeez3mxz2n1WHTNE7n +233: 5EYCAe5jLQhn6ofDSwvUwvS78rKZ3iYXPezHWvicULABe9U8 +234: 5EYCAe5jLQhn6ofDSwvkgwyhFLzkWGeQ8Kvo4sQSwA2uudWf +235: 5EYCAe5jLQhn6ofDSww2RyXHMqfwxpkGrzsJcp6HPyueBKKS +236: 5EYCAe5jLQhn6ofDSwwJB14sULM9RNr9bfopAkn7ronNSouy +237: 5EYCAe5jLQhn6ofDSwwZv2cTaq2Lsvx2LLkKihTxKdf6iUQ9 +238: 5EYCAe5jLQhn6ofDSwwqf4A3hKhYLV3u51gqGe9nnTXpz5KG +239: 5EYCAe5jLQhn6ofDSwx7Q5hdopNjo39mogdLpaqdFHQZFjX1 +240: 5EYCAe5jLQhn6ofDSwxP97FDvK3wFbFeYMZrNXXTi7HHXSVQ +241: 5EYCAe5jLQhn6ofDSwxet8np2oj8i9MXH2WMvUDJAwA1nq7R +242: 5EYCAe5jLQhn6ofDSwxvdALQ9JQLAhTQ1hSsUQu8dm2k4jo3 +243: 5EYCAe5jLQhn6ofDSwyCNBszFo5XdFZGkNPP2May6auULR3m +244: 5EYCAe5jLQhn6ofDSwyU7DRaNHkj5of9V3KtaJGoZQnCbxRj +245: 5EYCAe5jLQhn6ofDSwyjrEyAUnRvYMm2DiGQ8Exe2Eevsbos +246: 5EYCAe5jLQhn6ofDSwz1bGWkbH77zurtxPCugBeUV4Xf9FEy +247: 5EYCAe5jLQhn6ofDSwzHLJ4LhmnKTTxmh49RE8LJwtQPQuPs +248: 5EYCAe5jLQhn6ofDSwzZ5KbvpGTWv24eRj5vn529QiH7gWns +249: 5EYCAe5jLQhn6ofDSwzppM9Wvm8iNaAXAQ2SL1hysY9qx3ao +250: 5EYCAe5jLQhn6ofDSx16ZNh73Fouq8GPu4xwsxPpLN2aDciL +251: 5EYCAe5jLQhn6ofDSx1NJQEh9kV7HgNGdjuTRu5eoBuJVHP9 +252: 5EYCAe5jLQhn6ofDSx1e3RnHGFAJkEU9NQqxyqmVG1n2kz46 +253: 5EYCAe5jLQhn6ofDSx1unTKsNjqWCna275nUXnTKiqem2beu +254: 5EYCAe5jLQhn6ofDSx2BXUsTVEWhfLftqkiz5j9ABfXVHzQ2 +255: 5EYCAe5jLQhn6ofDSx2TGWR3bjBu7tmmaRfVdfpzeVQDZscZ +256: 5EYCAe5jLQhn6ofDSvqFAHPozxdzP66nvfzRhb4qEUHpQXPv +257: 5EYCAe5jLQhn6ofDSvqWuJwQ7TKBqeCffLvwFXkfhJAYgD3P +258: 5EYCAe5jLQhn6ofDSvqneLUzDwzPJCJYQ1sSoUSWA83GwgQt +259: 5EYCAe5jLQhn6ofDSvr4PN2aLSfakkQR8goxMR8Lcwv1DSbq +260: 5EYCAe5jLQhn6ofDSvrL8PaASwLnDJWHsMkTuMpB5mnjUseM +261: 5EYCAe5jLQhn6ofDSvrbsR7kZS1yfrcAc2gyTJW1YbfTkXuS +262: 5EYCAe5jLQhn6ofDSvrscSfLfvhB8Qi3LhdV1FBr1RYC28tL +263: 5EYCAe5jLQhn6ofDSvs9MUCvnRNNaxov5NZzZBsgUFQvHj55 +264: 5EYCAe5jLQhn6ofDSvsR6VkWtv3a3Wunp3WW78ZWw5HeZQAP +265: 5EYCAe5jLQhn6ofDSvsgqXJ71QimW51fYiT1f5FMPuANqDNX +266: 5EYCAe5jLQhn6ofDSvsxaYqh7uPxxd7YHPPXD1wBrj376tWY +267: 5EYCAe5jLQhn6ofDSvtEKaPHEQ5ARBDR24L2kxd2KYuqNPar +268: 5EYCAe5jLQhn6ofDSvtW4bvsLtkMsjKHkjGYJuJrnNnZe4bY +269: 5EYCAe5jLQhn6ofDSvtmodUTTPRZLHRAVQD3rqzhFCfHuYa9 +270: 5EYCAe5jLQhn6ofDSvu3Yf23Zt6knqX3E59ZQngXi2Y2BNLJ +271: 5EYCAe5jLQhn6ofDSvuKHgZdgNmxFPcuxk64xjNNArQkSnAa +272: 5EYCAe5jLQhn6ofDSvub2i7DnsT9hwinhR2aWg4CdgHUiRdK +273: 5EYCAe5jLQhn6ofDSvurmjeouN8MAVpfS5y64ck36WACzBoE +274: 5EYCAe5jLQhn6ofDSvv8WmCQ1roYd3vYAkubcZRsZL2wFmUp +275: 5EYCAe5jLQhn6ofDSvvQFnjz8MUk5c2QuRr7AW7i29ufXLBs +276: 5EYCAe5jLQhn6ofDSvvfzpHaEr9wYA8He6nciSoYUynPo1wJ +277: 5EYCAe5jLQhn6ofDSvvwjqqAMLq8ziEANmj8GPVNwof84VTF +278: 5EYCAe5jLQhn6ofDSvwDUsNkTqWLTGL37SfdpLBDQdXrLLVP +279: 5EYCAe5jLQhn6ofDSvwVDtvLaLBXupRur7c9NGs3sTQabobG +280: 5EYCAe5jLQhn6ofDSvwkxvTvgprjNNXnanYevDYtLHHJsUWQ +281: 5EYCAe5jLQhn6ofDSvx2hx1WoKXvpvdfKTVAUAEio7A394VB +282: 5EYCAe5jLQhn6ofDSvxJSyZ6upD8HUjY48Rg26vZFw2mQtmG +283: 5EYCAe5jLQhn6ofDSvxaC16h2JtKk2qQnoNBa3cPikuVgH2a +284: 5EYCAe5jLQhn6ofDSvxqw2eH8oZXCawHXUJh7zJEBanDwyyQ +285: 5EYCAe5jLQhn6ofDSvy7g4BsFJEif93AG9FCfvz4eQexDirh +286: 5EYCAe5jLQhn6ofDSvyPR5jTMnuv7h92zpBiDsfu7EXgVLDf +287: 5EYCAe5jLQhn6ofDSvyfA7H3UHb7aFEujV8DmpMja4QQknoB +288: 5EYCAe5jLQhn6ofDSvyvu8pdanGK2oLnUA4jKm3a2tH92NjE +289: 5EYCAe5jLQhn6ofDSvzCeANDhGwWVMSfCq1EshjQVi9sJ6eA +290: 5EYCAe5jLQhn6ofDSvzUPBuoomchwuYXwVwkReRExY2bZe1S +291: 5EYCAe5jLQhn6ofDSvzk8DTPvGHuQTeQgAtFyb75RMuKqVPu +292: 5EYCAe5jLQhn6ofDSw11sEzz2ky6s1kHQqpmXXnutBn46shJ +293: 5EYCAe5jLQhn6ofDSw1HcGYa9FeJKZrA9WmH5UUkM1enNeCq +294: 5EYCAe5jLQhn6ofDSw1ZMJ6AFkKVn7x2tBhndRAaoqXWeDgU +295: 5EYCAe5jLQhn6ofDSw1q6KdkNEzhEg3ucreJBMrRGfQEuqcy +296: 5EYCAe5jLQhn6ofDSw26qMBLUjfthE9nMXaojJYFjVGyBbDv +297: 5EYCAe5jLQhn6ofDSw2NaNivbEM69nFf6CXKHFE6CK9hT1az +298: 5EYCAe5jLQhn6ofDSw2eKQGWhj2HcLMXpsTpqBuvf92Rie2g +299: 5EYCAe5jLQhn6ofDSw2v4Rp6pDhV4tTQZYQLP8bm7xu9zEfU +300: 5EYCAe5jLQhn6ofDSw3BoTMgviNgXSZHJDLqw5HbanmtFw81 +301: 5EYCAe5jLQhn6ofDSw3TYUuH3D3syzfA2tHMV1yS3cecXkzL +302: 5EYCAe5jLQhn6ofDSw3jHWSs9hj5SYm2mZDs2xfGWSXLoPFN +303: 5EYCAe5jLQhn6ofDSw412XzTGCQGu6ruWEANauM6yGQ54y3V +304: 5EYCAe5jLQhn6ofDSw4GmZY3Nh5UMexnEu6t8r2wS6GoLd6G +305: 5EYCAe5jLQhn6ofDSw4YWb5dVBkfpD4eya3Pgnimtv9XcAHv +306: 5EYCAe5jLQhn6ofDSw4pFcdDbgRsGmAXiEyuEjQcMk2Fso4J +307: 5EYCAe5jLQhn6ofDSw55zeAoiB74jKGQSuvQng6SpZtz9Vxy +308: 5EYCAe5jLQhn6ofDSw5MjfiPpfnGBsNHBarvLcnHHPmiQteL +309: 5EYCAe5jLQhn6ofDSw5dUhFywATTeRU9vFoRtZU7kDeSgbg2 +310: 5EYCAe5jLQhn6ofDSw5uDioa3f8f6ya2evjwSW9xD3XAxAx1 +311: 5EYCAe5jLQhn6ofDSw6AxkMAA9orZXfuPbgSzSqnfsPuDqwL +312: 5EYCAe5jLQhn6ofDSw6ShmtkGeV425mn8GcxYPXd8hGdVc6w +313: 5EYCAe5jLQhn6ofDSw6iSoSLP9AFUdserwZU6LDTbX9Mm6rm +314: 5EYCAe5jLQhn6ofDSw6zBpyvVdqSwByXbcVyeGuJ4M262q6Q +315: 5EYCAe5jLQhn6ofDSw7FvrXWc8WePk5QLHSVCDb8XAtpJXc2 +316: 5EYCAe5jLQhn6ofDSw7Xft56idBqrJBH4xNzkAGxyzmYa7Ff +317: 5EYCAe5jLQhn6ofDSw7oQucgq7s3JrH9odKWJ6xoSpeGqdqm +318: 5EYCAe5jLQhn6ofDSw859wAGwcYEmQP2YJG1r3edueX17Sh6 +319: 5EYCAe5jLQhn6ofDSw8Ltxhs47DSDxUuGyCXPzLUNUPjP1sE +320: 5EYCAe5jLQhn6ofDSw8cdzFTAbtdgWan1e92ww2JqJGTedjU +321: 5EYCAe5jLQhn6ofDSw8tP1o3H6Zq94gekK5YVsi9J89Bv64S +322: 5EYCAe5jLQhn6ofDSw9A83LdPbF2bcnXUz243pPykx1vBosi +323: 5EYCAe5jLQhn6ofDSw9Rs4tDW5vE4AtQDexZbm5pDmteTYXr +324: 5EYCAe5jLQhn6ofDSw9hc6RocabRWizGxKu59hmegbmNj178 +325: 5EYCAe5jLQhn6ofDSw9yM7yPj5GcyH69gzqaheTV9Re6zjMq +326: 5EYCAe5jLQhn6ofDSwAF69WyqZwpRqC2Rfn6Fb9KcFWqGBTn +327: 5EYCAe5jLQhn6ofDSwAWqB4Zx4d1tPHuALiboXqA55PZXq5E +328: 5EYCAe5jLQhn6ofDSwAnaCcA4ZJDLwPmu1f7MUWzXuGHoXBP +329: 5EYCAe5jLQhn6ofDSwB4KE9kB3yQoVVedgbcuRCpzj9254yw +330: 5EYCAe5jLQhn6ofDSwBL4FhLHYecG3bXNMY8TMtfTZ1kLpho +331: 5EYCAe5jLQhn6ofDSwBboHEvQ3KoibhQ72Ue1JaVvNtUcXUJ +332: 5EYCAe5jLQhn6ofDSwBsYJnWWY11B9oGqhR9ZFGLPCmCt89h +333: 5EYCAe5jLQhn6ofDSwC9HLL6d2gCdhu9aNMf7BxAr2dw9ppe +334: 5EYCAe5jLQhn6ofDSwCR2MsgjXMQ6G12K3JAf8e1JrWfRNDE +335: 5EYCAe5jLQhn6ofDSwCgmPRGr22bYp6u3iEgD5KqmgPPh3hX +336: 5EYCAe5jLQhn6ofDSwCxWQxrxWho1NCmnPBBm21gEWG7xc6b +337: 5EYCAe5jLQhn6ofDSwDEFSWT51NzTvJeX47hJxhWhL8rE71F +338: 5EYCAe5jLQhn6ofDSwDVzU43BW4BvUQXFj4CruPMAA1aVkSJ +339: 5EYCAe5jLQhn6ofDSwDmjVbdHzjPP2WPzPziQr5BcytJmWaH +340: 5EYCAe5jLQhn6ofDSwE3UX9DQVQaqacGj4wDxnm25om334HL +341: 5EYCAe5jLQhn6ofDSwEKDYgoWz5nJ8i9TjsjWjSrYddmJfht +342: 5EYCAe5jLQhn6ofDSwEaxaEPdUkykgp2CQpF4g8h1TWVaF57 +343: 5EYCAe5jLQhn6ofDSwErhbmyjySBDEutw5kkccpXUHPDqpD4 +344: 5EYCAe5jLQhn6ofDSwF8SdKZrU7Nfo1mfkhGAZWMw7Fx7Wbu +345: 5EYCAe5jLQhn6ofDSwFQBes9xxna8M7eQRdmiWCCPw8gPAnZ +346: 5EYCAe5jLQhn6ofDSwFfvgQk5TTmauDX96aHGSt2rm1QejQE +347: 5EYCAe5jLQhn6ofDSwFwfhxLBx8y3TKPsmWnpPZsKat8vLpQ +348: 5EYCAe5jLQhn6ofDSwGDQjVvJSpAW1RGcSTJNLFhnQksBuxZ +349: 5EYCAe5jLQhn6ofDSwGV9m3WQwVMxZX9M7PovGwYFEdbTqLQ +350: 5EYCAe5jLQhn6ofDSwGktnb6XSAZR7d25nLKUDdNi4WKjHVC +351: 5EYCAe5jLQhn6ofDSwH2dp8gdvqksfitpTGq2AKDAtP416pX +352: 5EYCAe5jLQhn6ofDSwHJNqgGkRWxLDpmZ8DLa713diFnGYZH +353: 5EYCAe5jLQhn6ofDSwHa7sDrrvC9nmveHo9r83gt6Y8WYAUE +354: 5EYCAe5jLQhn6ofDSwHqrtmSyQsMFL2X2U6MfzNiZN1EoxJG +355: 5EYCAe5jLQhn6ofDSwJ7bvK35uYYht8Pm92sDw4Z2Bsy5JYd +356: 5EYCAe5jLQhn6ofDSwJPLwrdCQDkASEGVoyNmskPV1khM3xf +357: 5EYCAe5jLQhn6ofDSwJf5yQDJttwczL9EUutKpSDwqdRcYKN +358: 5EYCAe5jLQhn6ofDSwJvpzwoRPa95YS1y9rPsm84QfW9tMQi +359: 5EYCAe5jLQhn6ofDSwKCa2VPXtFLY6XthpnuRhotsVNtA1nt +360: 5EYCAe5jLQhn6ofDSwKUK42yeNvXzedmSVjQyeVjLKFcRURc +361: 5EYCAe5jLQhn6ofDSwKk45aZksbjTCjeBAfvXbBZo98LhAFX +362: 5EYCAe5jLQhn6ofDSwL1o789sNGvukqWuqcS5XsQFy14xope +363: 5EYCAe5jLQhn6ofDSwLHY8fjyrx8NJwPeWYwdUZEinsoEZUW +364: 5EYCAe5jLQhn6ofDSwLZHADL6MdKps3GPBVTBRF5BckXW7BE +365: 5EYCAe5jLQhn6ofDSwLq2BkvCrJXHR997rRxjMvueSdFmhcW +366: 5EYCAe5jLQhn6ofDSwM6mDJWKLyijyF1rXNUHJck7GVz3PQs +367: 5EYCAe5jLQhn6ofDSwMNWEr6RqevCXLtbCJyqFJaa6NiJyR1 +368: 5EYCAe5jLQhn6ofDSwMeFGPgYLL7f5SmKsFVPBzR2vFSaVaJ +369: 5EYCAe5jLQhn6ofDSwMuzHwGeq1K7dYe4YBzw8gFVk8Ar7jR +370: 5EYCAe5jLQhn6ofDSwNBjKUrmKgWaBeWoD8WV5N5xZzu7st7 +371: 5EYCAe5jLQhn6ofDSwNTUM2SspMi2jkPXt52323vRPsdPTi7 +372: 5EYCAe5jLQhn6ofDSwNjDNa2zK2uVHrGGZ1XaxjktDkMezQq +373: 5EYCAe5jLQhn6ofDSwNzxQ7d6oi6wqx91Dx38uRbM3d5vkb5 +374: 5EYCAe5jLQhn6ofDSwPGhRfDDJPJQQ41jttYgr7RosVpCSnm +375: 5EYCAe5jLQhn6ofDSwPYSTCoKo4Vrx9tUZq4EnoGGhNYTsHL +376: 5EYCAe5jLQhn6ofDSwPpBUkPSHjhKWFmDEmZnjV6jXFGjavn +377: 5EYCAe5jLQhn6ofDSwQ5vWHyYnQtn4Mdwui5LgAwCM811FqV +378: 5EYCAe5jLQhn6ofDSwQMfXqZfH66EcTWgaeatcrmfAzjGwwQ +379: 5EYCAe5jLQhn6ofDSwQdQZP9mmmHhAZPRFb6SZYc7zsTYQ3S +380: 5EYCAe5jLQhn6ofDSwQu9avjtGSV9ifG9vXbzWESapkBpFWq +381: 5EYCAe5jLQhn6ofDSwRAtcUKzm7gcGm8tbU7YSvH3ecv5fQY +382: 5EYCAe5jLQhn6ofDSwRSde1v7Fnt4ps1dGQd6Pc7WUVeMKqG +383: 5EYCAe5jLQhn6ofDSwRiNfZWDkU5XNxtMwM8eLHwyJNNd1x9 +384: 5EYCAe5jLQhn6ofDSwRz7h76LF9Gyw4m6cHeCGynS8F6tUu4 +385: 5EYCAe5jLQhn6ofDSwSFriegSjpUSVAdqHE9kDfctx7qAGqb +386: 5EYCAe5jLQhn6ofDSwSXbkCGZEVfu3GWZxAfJAMTMmzZRjJj +387: 5EYCAe5jLQhn6ofDSwSoLmjrfjAsMbNPJd7Ar73HpbsHhKSv +388: 5EYCAe5jLQhn6ofDSwT55oHSnDr4p9UG3J3gQ3j8HRk1y3JJ +389: 5EYCAe5jLQhn6ofDSwTLppq2tiXGGha8mxzBwzQxkFckEpvZ +390: 5EYCAe5jLQhn6ofDSwTcZrNd1DCTjFg1WdvhVw6oD5VUWKxy +391: 5EYCAe5jLQhn6ofDSwTtJsvD7hsfBomtFJsD3sndfuNCmsJH +392: 5EYCAe5jLQhn6ofDSwUA3uToECYreMskyyoibpUU8jEw3T5N +393: 5EYCAe5jLQhn6ofDSwURnw1PLhE46uydiekE9mAJbZ7fKHH5 +394: 5EYCAe5jLQhn6ofDSwUhXxYyTBuFZU5WTKgjhhr94NzPakX9 +395: 5EYCAe5jLQhn6ofDSwUyGz6ZZgaT22BPBzdFFeXyXCs7rczx +396: 5EYCAe5jLQhn6ofDSwVF21e9gBFeUaHFvfZkobDoz2jr8F9t +397: 5EYCAe5jLQhn6ofDSwVWm3Bjnfvqw8P8fLWGMXueSrcaPq1Z +398: 5EYCAe5jLQhn6ofDSwVnW4jKuAc3PgV1Q1SmuUbUugVJfNVA +399: 5EYCAe5jLQhn6ofDSwW4F6Gv1fHErEat8gPHTRHKNWN2w5vR +400: 5EYCAe5jLQhn6ofDSwWKz7pW89xSJngksMKo1My9qLEmCh5V +401: 5EYCAe5jLQhn6ofDSwWbj9N6EeddmLndc2GJZJezJA7VUKPY +402: 5EYCAe5jLQhn6ofDSwWsUAugM9JqDttWLhCp7FLpkyzDjzxV +403: 5EYCAe5jLQhn6ofDSwX9DCTGTdz2gSzP5N9KfC2fDorx1RVV +404: 5EYCAe5jLQhn6ofDSwXQxDzra8fE916Fp35qD8iVgdjgHGPX +405: 5EYCAe5jLQhn6ofDSwXghFYSgdLRbZC8Yi2Lm5QL9TcQYr74 +406: 5EYCAe5jLQhn6ofDSwXxSH62o81d47J1HNxrK26AcHV8pFSS +407: 5EYCAe5jLQhn6ofDSwYEBJdcucgpWfPt23uMrxn157Ms5xvh +408: 5EYCAe5jLQhn6ofDSwYVvLBD27N1yDVkkiqsQuTqXwEbMX6v +409: 5EYCAe5jLQhn6ofDSwYmfMio8c3DRmbdVPnNxr9fzm7Kd75S +410: 5EYCAe5jLQhn6ofDSwZ3QPGPF6iQtKhWE4itWnqWTaz3tiZd +411: 5EYCAe5jLQhn6ofDSwZK9QoyMbPcLsoNxjfQ4jXLvQrnAT96 +412: 5EYCAe5jLQhn6ofDSwZatSMZU64ooRuFhQbucgDBPEjWS46h +413: 5EYCAe5jLQhn6ofDSwZrdTu9aak1Fz18S5YRAcu1r4cEhoLd +414: 5EYCAe5jLQhn6ofDSwa8NVSjh5RCiY71AkUviZarJtUxyQo6 +415: 5EYCAe5jLQhn6ofDSwaQ7WzKoa6QB6CsuRRSGWGgmiMhEyuu +416: 5EYCAe5jLQhn6ofDSwafrYXuv4mbdeJke6MwpSxXEYERWhTt +417: 5EYCAe5jLQhn6ofDSwawba5W2ZSo6CQdNmJTNPeMhN79n8Xw +418: 5EYCAe5jLQhn6ofDSwbDLbd6947zYkWW7SExvLLCAByt411A +419: 5EYCAe5jLQhn6ofDSwbV5dAgFYoC1JcNr7BUUH22d1rcKXhx +420: 5EYCAe5jLQhn6ofDSwbkpeiGN3UPTriFan7z2Dhs5qjLbAG1 +421: 5EYCAe5jLQhn6ofDSwc2ZgFrUY9avQp8KT4VaAPhYfc4rtSD +422: 5EYCAe5jLQhn6ofDSwcJJhoSb2pnNxv14811875Y1VUo8Udd +423: 5EYCAe5jLQhn6ofDSwca3jM2hXVyqX1snnwWg3mNUKMXQ7Lu +424: 5EYCAe5jLQhn6ofDSwcqnktcp2BBJ57kXTt2DzTCw9EFfjeB +425: 5EYCAe5jLQhn6ofDSwd7XnSCvWrNkdDdG8pXmw93Py6ywNA9 +426: 5EYCAe5jLQhn6ofDSwdPGoyo31XaDBKVzom3KspsrnyiCoBH +427: 5EYCAe5jLQhn6ofDSwdf1qXP9WCmfjRNjUhYspWiKcrSUZJy +428: 5EYCAe5jLQhn6ofDSwdvks4yFzsy8HXFU9e4RmCYnSjAkGv5 +429: 5EYCAe5jLQhn6ofDSweCVtcZNVZAaqd8CpaZyhtPFGbu1r89 +430: 5EYCAe5jLQhn6ofDSweUEvA9UzEN3PizwVX5XeaDi6UdHRW8 +431: 5EYCAe5jLQhn6ofDSwejywhjbUuZVwpsgATb5bG4AvMMYvzn +432: 5EYCAe5jLQhn6ofDSwf1iyFKhyakxVvkQqQ6dXwtdkE5pWEq +433: 5EYCAe5jLQhn6ofDSwfHTznupUFxR42d9WLcBUdj6a6p6RJP +434: 5EYCAe5jLQhn6ofDSwfZD2LVvxw9sc8VtBH7jRKZZPyYN3Qe +435: 5EYCAe5jLQhn6ofDSwfpx3t63TcMLAENcrDdHN1Q2DrGdXnV +436: 5EYCAe5jLQhn6ofDSwg6h5Rg9xHYniLFMXA8qJhEV3izuDDr +437: 5EYCAe5jLQhn6ofDSwgNS6yGGSxkFGS86C6ePFP4wsbjAhNK +438: 5EYCAe5jLQhn6ofDSwgeB8WrNwdwhpXzps39wC4uQhUTSNuL +439: 5EYCAe5jLQhn6ofDSwguvA4SVSK9ANdsZXyfV8kjsXMBi2rM +440: 5EYCAe5jLQhn6ofDSwhBfBc2bvzLcvjkJCvB35SaLMDuyoqD +441: 5EYCAe5jLQhn6ofDSwhTQD9ciRfY5Uqd2srgb28QoB6eFK1Z +442: 5EYCAe5jLQhn6ofDSwhj9EhCpvLjY2wVmYoC8xpFFzyNWvEr +443: 5EYCAe5jLQhn6ofDSwhztGEnwR1vzb3NWDjhguW5ipr6nXHN +444: 5EYCAe5jLQhn6ofDSwiGdHnP3uh8T99FEtgDErBvBeiq45cG +445: 5EYCAe5jLQhn6ofDSwiYNKKyAQNKuhF7yZcinnskeUbZKgnF +446: 5EYCAe5jLQhn6ofDSwip7LsZGu3XNFLziEZELjZb7JUHbZzu +447: 5EYCAe5jLQhn6ofDSwj5rNR9PPiipoSsSuVjtgFRa8M1s5jf +448: 5EYCAe5jLQhn6ofDSwjMbPxjVtPvHMYkBaSFScwG2xDk8eCi +449: 5EYCAe5jLQhn6ofDSwjdLRWKcP57juecvFNkzZd6Vn6UQFZC +450: 5EYCAe5jLQhn6ofDSwju5T3uiskKCTkVevKGYWJvxbyCg4Jv +451: 5EYCAe5jLQhn6ofDSwkApUbVqNRWf1rNPbFn6SzmRRqvwSdW +452: 5EYCAe5jLQhn6ofDSwkSZW95ws6i7ZxF8GCHePgbtFifDEja +453: 5EYCAe5jLQhn6ofDSwkiJXgg4Mmua847rw8oCLNSM5bPUoyW +454: 5EYCAe5jLQhn6ofDSwkz3ZEGArT72g9zbc5JkH4GouU7kW6c +455: 5EYCAe5jLQhn6ofDSwmFnamrHM8JVEFsLH1pJDk7GjLr27EN +456: 5EYCAe5jLQhn6ofDSwmXXcKSPqoVwnMk4wxKrARwjZDaHjGj +457: 5EYCAe5jLQhn6ofDSwmoGds2WLUhQLTcoctqQ77nCP6JZSt5 +458: 5EYCAe5jLQhn6ofDSwn51fQccq9trtZVYHqLx3ocfCy2pusw +459: 5EYCAe5jLQhn6ofDSwnLkgxCjKq6KSfNGxmrVzVT82qm6X4V +460: 5EYCAe5jLQhn6ofDSwncViVnqpWHmzmF1diN3wBHariVNDY4 +461: 5EYCAe5jLQhn6ofDSwntEk3NxKBVEYs7kJesbss83gbDdh5y +462: 5EYCAe5jLQhn6ofDSwo9ymay4orgh6xzUybP9pYxWWTwuZdk +463: 5EYCAe5jLQhn6ofDSwoRio8ZBJXt9f4sDeXthmEnyLLgAtRS +464: 5EYCAe5jLQhn6ofDSwohTpg9HoD5cDAjxKUQFhvdSADQSd7q +465: 5EYCAe5jLQhn6ofDSwoyCrDjQHtH4mGcgzQuoecTtz68iBNB +466: 5EYCAe5jLQhn6ofDSwpEwsmKWnZUXKNVRfMRMbJJMoxrz5ZA +467: 5EYCAe5jLQhn6ofDSwpWguJudHEfysUNALHvuXz8pdqbFU2C +468: 5EYCAe5jLQhn6ofDSwpnRvrVjmusSRaEu1ESTUfyHTiKX3yD +469: 5EYCAe5jLQhn6ofDSwq4AxQ5rGb4tyg7dgAx1RMokHb3nmAN +470: 5EYCAe5jLQhn6ofDSwqKuywfxmGGMXmzNM7TZN3eD7Tn4RDB +471: 5EYCAe5jLQhn6ofDSwqbf1VG5FwTp5ss723y7JjUfwLWL6mj +472: 5EYCAe5jLQhn6ofDSwqsQ32rBkcfGdyjqgzUfFRK8mDEbpVV +473: 5EYCAe5jLQhn6ofDSwr994aSJFHrjC5caMvzDC79bb5xsU5M +474: 5EYCAe5jLQhn6ofDSwrQt682Qjy4BkBVK2sVm8nz4Qxh8rdZ +475: 5EYCAe5jLQhn6ofDSwrgd7fcXEeFeJHN3hp1K5UpXEqRQQvd +476: 5EYCAe5jLQhn6ofDSwrxN9DCdjKT6rPEnNkWs2Aez4i9g7hy +477: 5EYCAe5jLQhn6ofDSwsE7AknkDzeZQV7X3h2QxrVStaswkrq +478: 5EYCAe5jLQhn6ofDSwsVrCJNrifr1xazFidXxuYKuiTcDVjH +479: 5EYCAe5jLQhn6ofDSwsmbDqxyDM3UWgrzPa3WrEANYLLUw1X +480: 5EYCAe5jLQhn6ofDSwt3LFPZ5i2Ew4njj4WZ4nuzqND4kbZN +481: 5EYCAe5jLQhn6ofDSwtK5Gw9CChSPctcTjT4cjbqJC5o2PJV +482: 5EYCAe5jLQhn6ofDSwtapJUjJhNdrAzVCQPaAgHfm1xXHtKK +483: 5EYCAe5jLQhn6ofDSwtrZL2KRC3qJj6Mw5L5icyWDqqFZadE +484: 5EYCAe5jLQhn6ofDSwu8JMZuXgj2mHCEfkGbGZfLgfhyqAhn +485: 5EYCAe5jLQhn6ofDSwuQ3P7VeBQEDqJ7QRD6pWMB9Vai6mth +486: 5EYCAe5jLQhn6ofDSwufnQf5kg5RgPPz969cNT31cKTSNSCS +487: 5EYCAe5jLQhn6ofDSwuwXSCfsAkd8wVrsm67vPir59LAe42A +488: 5EYCAe5jLQhn6ofDSwvDGTkFyfRpbVbjcS2dULQgXyCtubBX +489: 5EYCAe5jLQhn6ofDSwvV1VHr6A7243hcM6y92H6Wzo5dBP9F +490: 5EYCAe5jLQhn6ofDSwvkkWqSCenDWboV5mueaDnMTcxMT382 +491: 5EYCAe5jLQhn6ofDSww2VYP2K9TQy9uMpSrA8AUBvSq5iXaj +492: 5EYCAe5jLQhn6ofDSwwJEZvcRe8cRi1EZ7nfg7A2PGhoz9d6 +493: 5EYCAe5jLQhn6ofDSwwZybUCY8ootG77HnjBE3qrr6aYFvzB +494: 5EYCAe5jLQhn6ofDSwwqid1nedV1LpCz2TfgmzXhJvTGXUBY +495: 5EYCAe5jLQhn6ofDSwx7TeZNm8ACoNJrm8cCKwDXmkKznwLK +496: 5EYCAe5jLQhn6ofDSwxPCg6xscqQFvQjVoYhssuNEaCj4cV1 +497: 5EYCAe5jLQhn6ofDSwxewheYz7WbiUWcEUVDRpbChQ5TLKHR +498: 5EYCAe5jLQhn6ofDSwxvgjC96cBoB2cUy9RiymH3ADxBc4Lb +499: 5EYCAe5jLQhn6ofDSwyCRkjjD6rzdaiMhpNEXhxsd3pusccP +500: 5EYCAe5jLQhn6ofDSwyUAnHKKbYC68pESVJk5eei5she97qy +501: 5EYCAe5jLQhn6ofDSwyjuopuS6DPYgv7BAFFdbLYYhaNQuf9 +502: 5EYCAe5jLQhn6ofDSwz1eqNVYatb1F1yuqBmBY2P1XT6gLkd +503: 5EYCAe5jLQhn6ofDSwzHPrv5f5ZnTo7reW8GjUiDUMKpwzz6 +504: 5EYCAe5jLQhn6ofDSwzZ8tTfmaEyvMDjPB4nHRQ3wBCZDsZs +505: 5EYCAe5jLQhn6ofDSwzpsv1Ft4vBNuKc7r1HqN5tQ15HVCrz +506: 5EYCAe5jLQhn6ofDSx16cwYqzZbNqTRUrWwoPJmirpx1kybJ +507: 5EYCAe5jLQhn6ofDSx1NMy6S74GaJ1XMbBtJwFTZKepk2ghP +508: 5EYCAe5jLQhn6ofDSx1e6ze2DYwmkZdEKrppVC9PnUhUJ51w +509: 5EYCAe5jLQhn6ofDSx1ur2BcL3cyD7j74XmL38qEFJaCZfuR +510: 5EYCAe5jLQhn6ofDSx2Bb3jCSYJAffpyoChqb5X4i8SvqbpQ +511: 5EYCAe5jLQhn6ofDSx2TL5GnZ2yN8DvrXseM92CuAxKf7ELV +512: 5EYCAe5jLQhn6ofDSvqFDrFYxGRTPRFst7yHCwSjkwDFwear +513: 5EYCAe5jLQhn6ofDSvqWxso94m6eqyMkcnunkt8aDm5zDaY6 +514: 5EYCAe5jLQhn6ofDSvqnhuLjBFmrJXTdMTrJJppQgaxiV33E +515: 5EYCAe5jLQhn6ofDSvr4SvtKHkT3m5ZW68normWF9QqSkkTc +516: 5EYCAe5jLQhn6ofDSvrLBxRuQF8FDdfNpojKQiC5cEiB2Sk4 +517: 5EYCAe5jLQhn6ofDSvrbvyyVWjoSgBmFZUfpxesv54auJ2W6 +518: 5EYCAe5jLQhn6ofDSvrsg1X5dEUe8js8J9cLWbZkXtTdZh9r +519: 5EYCAe5jLQhn6ofDSvs9R34fjj9qbHy12pYr4YFaziLMqJTN +520: 5EYCAe5jLQhn6ofDSvsRA4cFrDq33r4smVVMcUwRTYD66mFA +521: 5EYCAe5jLQhn6ofDSvsgu69qxiWEWQAkWARsARdFvN5pNJkh +522: 5EYCAe5jLQhn6ofDSvsxe7hS5DBRxxGdEqNNiNK6PBxYdy7w +523: 5EYCAe5jLQhn6ofDSvtEP9F2BhrdRWNVyWJtGJzvr1qGuotj +524: 5EYCAe5jLQhn6ofDSvtW8AncJCXpt4UNiBFPpFgmJqi1BLVs +525: 5EYCAe5jLQhn6ofDSvtmsCLCQhD2LcaFSrBuNCNbmfajSpjE +526: 5EYCAe5jLQhn6ofDSvu3cDsnXBtDoAg8BX8Qv94SEVTTiiQ6 +527: 5EYCAe5jLQhn6ofDSvuKMFRNdgZRFimzvC4vU5kGhKLBzAn6 +528: 5EYCAe5jLQhn6ofDSvub6GxxkBEciGsses1S22S7A9CvFx62 +529: 5EYCAe5jLQhn6ofDSvurqJWYrfupApykPXwwZy7wcy5eXHgT +530: 5EYCAe5jLQhn6ofDSvv8aL48yAb1dP5d8CtT7uon5nxNoAHh +531: 5EYCAe5jLQhn6ofDSvvQKMbj5fGD5wBVrspxfrVcYcq74cff +532: 5EYCAe5jLQhn6ofDSvvg4P9KC9wQYVHNbYmUDoBT1ShqLTbC +533: 5EYCAe5jLQhn6ofDSvvwoQguJecc13PFLDhymjsHUGaZc2LL +534: 5EYCAe5jLQhn6ofDSvwDYSEVR9HoTbV84teVKgZ7w6THsXG4 +535: 5EYCAe5jLQhn6ofDSvwVHTn5Xdxzv9azoZazsdExPvL29Fyn +536: 5EYCAe5jLQhn6ofDSvwm2VKfe8eCNhgsYEXWRZvnrkCkQm3z +537: 5EYCAe5jLQhn6ofDSvx2mWsFkdKPqFnkGuU1yWcdKa5UgYgt +538: 5EYCAe5jLQhn6ofDSvxJWYQqs7zbHotd1aQXXTJTnPxCx4qw +539: 5EYCAe5jLQhn6ofDSvxaFZxRycfnkMzVkFM35PzJFDpwDdau +540: 5EYCAe5jLQhn6ofDSvxqzbW267LzCv6NUvHYdLg8i3hfVTFu +541: 5EYCAe5jLQhn6ofDSvy7jd3cCc2BfUCFDbE4BHMyAsaPm1sJ +542: 5EYCAe5jLQhn6ofDSvyPUebCK6hP82J7xGAZjE3odhT82USX +543: 5EYCAe5jLQhn6ofDSvyfDg8nRbNaaaPzgw75HAje6XKrJNeZ +544: 5EYCAe5jLQhn6ofDSvyvxhgNY63n38VsRc3aq7RUZMCaZzZ9 +545: 5EYCAe5jLQhn6ofDSvzChjDxeaiyVgbkAGz6P47K2B5JqJmC +546: 5EYCAe5jLQhn6ofDSvzUSkmYm5QAxEhctwvbvzo9Uzx375yn +547: 5EYCAe5jLQhn6ofDSvzkBnK8sa5NQnoVdcs7UwUywppmNkyL +548: 5EYCAe5jLQhn6ofDSw11voriz4kZsLuNNHod2tApQehVeFiH +549: 5EYCAe5jLQhn6ofDSw1HfqQK6ZRmKu1F6xk8apresUaDuoLZ +550: 5EYCAe5jLQhn6ofDSw1ZQrwuD46xnT77qdge8mYVLJSxBd2D +551: 5EYCAe5jLQhn6ofDSw1q9tVVKYnAF1CzaJd9giEKo8KgTFV2 +552: 5EYCAe5jLQhn6ofDSw26tv35S3TMhZJsJyZfEevAFxCQireQ +553: 5EYCAe5jLQhn6ofDSw2NdwafYY8ZA7Qk3eWAnbbzin58zS6X +554: 5EYCAe5jLQhn6ofDSw2eNy8Ff2okcfWcnKSgLYHqBbwsG4y5 +555: 5EYCAe5jLQhn6ofDSw2v7zfqmXUx5DcVWzPBtUyfeRpbXoLx +556: 5EYCAe5jLQhn6ofDSw3Bs2DRt2A9XmiNFfKhSRfW7FhKoSHv +557: 5EYCAe5jLQhn6ofDSw3Tc3m1zWqLzKpEzLGCzNMLa5a457dP +558: 5EYCAe5jLQhn6ofDSw3jM5Jc71WYSsv7j1CiYK3B2uSnLbvm +559: 5EYCAe5jLQhn6ofDSw4166rCDWBjuS1zTg9E6Fj1VjKWcGKu +560: 5EYCAe5jLQhn6ofDSw4Gq8PnKzrwMz7sCM5jeCQqxZCEsiEp +561: 5EYCAe5jLQhn6ofDSw4Ya9wNSVY8pYDjw22FC96gRP4y9dUg +562: 5EYCAe5jLQhn6ofDSw4pKBUxYzDLH6Kcfgxkk5nWtCwhR9aG +563: 5EYCAe5jLQhn6ofDSw564D2YfUtXjeRVQMuGJ2UMM2pRghUV +564: 5EYCAe5jLQhn6ofDSw5MoEa8myZjCCXN92qmqyABorh9xK4t +565: 5EYCAe5jLQhn6ofDSw5dYG7itUEvekdEshnHPur2GgZtE7i9 +566: 5EYCAe5jLQhn6ofDSw5uHHfJzxv87Jj7cNinwrXrjWScVjpQ +567: 5EYCAe5jLQhn6ofDSw6B2KCu7TbKZrpzM3fJVoDhCLKLmP5E +568: 5EYCAe5jLQhn6ofDSw6SmLkVDxGX2Qvs5ibp3juXfAC52pBg +569: 5EYCAe5jLQhn6ofDSw6iWNJ5LSwiUy2jpPYKbgbN7z4oJPDJ +570: 5EYCAe5jLQhn6ofDSw6zFPqfSwcuwX8cZ4Uq9dHCaowXZxCq +571: 5EYCAe5jLQhn6ofDSw7FzRPFZSJ7Q5EVHjRLhZy33dpFqdiY +572: 5EYCAe5jLQhn6ofDSw7XjSvqfvyJrdLN2QMrFWesWTgz7Wb2 +573: 5EYCAe5jLQhn6ofDSw7oUUURnReWKBSEm5JMoTLhyHZiNqXY +574: 5EYCAe5jLQhn6ofDSw85DW21tvKhmjY7VkEsMQ2YS7SSeWt4 +575: 5EYCAe5jLQhn6ofDSw8LxXZc1QzuEHdzERBNuLiNtwKAv6Pe +576: 5EYCAe5jLQhn6ofDSw8chZ7C7ug6gqjry67tTHQDMmBuC1de +577: 5EYCAe5jLQhn6ofDSw8tSaenEQMJ9Pqjhm4Q1E63pb4dTM7S +578: 5EYCAe5jLQhn6ofDSw9ABcCNLu2VbwwcSRzuZAmtHQwMj1Cb +579: 5EYCAe5jLQhn6ofDSw9RvdjxTPhh4W3VB6wR77TikEp5ze9D +580: 5EYCAe5jLQhn6ofDSw9hffHYZtNtX49Mumsvf49ZD4gpGUGb +581: 5EYCAe5jLQhn6ofDSw9yQgq8gP45ycFEeSpSCzqPftZYY8c6 +582: 5EYCAe5jLQhn6ofDSwAF9iNinsjHSAM7P7kwkwXE8iSGofY4 +583: 5EYCAe5jLQhn6ofDSwAWtjvJuNQUtiSz7nhTJtD4bYK15Mwa +584: 5EYCAe5jLQhn6ofDSwAndmTu1s5gMGYrrTdxrptu4NBjLm3i +585: 5EYCAe5jLQhn6ofDSwB4No1V8Mksopejb8aUQmajXC4TcdTi +586: 5EYCAe5jLQhn6ofDSwBL7pZ5ErS5GNkcKoWyxiGZz1wBt1hh +587: 5EYCAe5jLQhn6ofDSwBbrr6fMM7GivrV4UTVWexQSqov9udn +588: 5EYCAe5jLQhn6ofDSwBsbseFTqnUBUxMo9Q14beEufgeRF5g +589: 5EYCAe5jLQhn6ofDSwC9LuBqaLTfe34EXpLWcYL5NVZNguqD +590: 5EYCAe5jLQhn6ofDSwCR5vjRgq8s6bA7GVH2AV1uqKS6xivf +591: 5EYCAe5jLQhn6ofDSwCgpxH1oKp4Z9Fz1ADXiRhkJ9JqEH3f +592: 5EYCAe5jLQhn6ofDSwCxZypbupVG1hMrjqA3GNPakyBZW2hz +593: 5EYCAe5jLQhn6ofDSwDEK1NC2KATUFTjUW6YpK5RDo4Hmbw9 +594: 5EYCAe5jLQhn6ofDSwDW42un8oqevoZcDB34NFmFgcw23A4Q +595: 5EYCAe5jLQhn6ofDSwDmo4TNFJWrPMfUwqyZvCT69SokJrjA +596: 5EYCAe5jLQhn6ofDSwE3Y5zxMoC3qumMgWv5U98vcGgUaM83 +597: 5EYCAe5jLQhn6ofDSwEKH7YYUHsFJTsERBrb25pm56ZCr2CG +598: 5EYCAe5jLQhn6ofDSwEb2968anYSm1y79ro6a2WbXvRw7i4R +599: 5EYCAe5jLQhn6ofDSwErmAdihHDeDa4ytXjc7yCRzkJfPCoW +600: 5EYCAe5jLQhn6ofDSwF8WCBJomtqg8ArdCg7futGTaBPev5r +601: 5EYCAe5jLQhn6ofDSwFQFDitvGa38gGjMscdDra6vQ47vagE +602: 5EYCAe5jLQhn6ofDSwFfzFGV2mFEbENc6YZ8moFwPDvrCCj6 +603: 5EYCAe5jLQhn6ofDSwFwjGp59FvS3nUUqDVeKjwmr3oaTkqS +604: 5EYCAe5jLQhn6ofDSwGDUJMfFkbdWLaMZtS9sgdcJsgJjJF4 +605: 5EYCAe5jLQhn6ofDSwGVDKuFNFGpxtgEJZNfRdKSmhZ2zvJd +606: 5EYCAe5jLQhn6ofDSwGkxMSqUjx2RSn73EKAya1HEXRmGjcm +607: 5EYCAe5jLQhn6ofDSwH2hNzRbEdDszsymuFgXWh7hMJVY8Fk +608: 5EYCAe5jLQhn6ofDSwHJSQY1hjJRLYyrWaCC5TNxABBDonmo +609: 5EYCAe5jLQhn6ofDSwHaBS5bpDyco75jFF8hdQ4nd13x5VQN +610: 5EYCAe5jLQhn6ofDSwHqvTdBviepFfBbyv5DBLkd5pvgM2q6 +611: 5EYCAe5jLQhn6ofDSwJ7fVAn3DL1iDHUib1ijHSTYeoQcmDP +612: 5EYCAe5jLQhn6ofDSwJPQWiN9i1DAmPMTFxEHE8J1Ug8tTWG +613: 5EYCAe5jLQhn6ofDSwJf9YFxGCgQdKVEBvtjqAp8UJYs9xDb +614: 5EYCAe5jLQhn6ofDSwJvtZoYNhMc5sb6vbqFP7Vxw8RbReGD +615: 5EYCAe5jLQhn6ofDSwKCdbM8VC2oYRgyfGmkw4BoPxJKhPnV +616: 5EYCAe5jLQhn6ofDSwKUNctibghzzynrPwiGUzsdrnB3xs32 +617: 5EYCAe5jLQhn6ofDSwKk7eSJiBPCTXtj8cen2wZUKc3nESFM +618: 5EYCAe5jLQhn6ofDSwL1rfytpg4Pv5zbsHbHatFJnRvWW1je +619: 5EYCAe5jLQhn6ofDSwLHbhXUwAjbNe6UbxXo8pw9FFoEms63 +620: 5EYCAe5jLQhn6ofDSwLZLj553fQnqCCMLdUJgmcyi5fy3Gdi +621: 5EYCAe5jLQhn6ofDSwLq5kcfAA5zHkJE5JQpEiJpAuYhJzsm +622: 5EYCAe5jLQhn6ofDSwM6pnAFGemBkJQ6oyMKnezedjRRaevZ +623: 5EYCAe5jLQhn6ofDSwMNZohqP9SPCrVyYeHqLbgV6ZJ9rGoC +624: 5EYCAe5jLQhn6ofDSwMeJqFRVe7afQbrHKELtYNKZPAt7wnT +625: 5EYCAe5jLQhn6ofDSwMv3ro1c8nn7xhj1zArSV4A2D3cPfMu +626: 5EYCAe5jLQhn6ofDSwNBntLbidTyaWobkf7MzRjzV2vLfF6h +627: 5EYCAe5jLQhn6ofDSwNTXutBq89B34uUVL3sYNRpwro4vqqw +628: 5EYCAe5jLQhn6ofDSwNjGwRmwcpNVd1MDzzP6K7fQgfoCQtG +629: 5EYCAe5jLQhn6ofDSwP11xyN47VZxB7DxfvteFoVsWYXUAVF +630: 5EYCAe5jLQhn6ofDSwPGkzWxAcAmQjD6hLsQCCVLLLRFjZ9g +631: 5EYCAe5jLQhn6ofDSwPYW24YH6qxsHJyS1ouk9BAoAHz1CWW +632: 5EYCAe5jLQhn6ofDSwPpF3c8PbXAKqQrAgkRJ5s1FzAiGwZa +633: 5EYCAe5jLQhn6ofDSwQ5z59iW6CMnPWiuMgvr2Yqip3SYVED +634: 5EYCAe5jLQhn6ofDSwQMj6hJcasZEwcbe2dSPyEgBdvApCdf +635: 5EYCAe5jLQhn6ofDSwQdU8Etj5YkhViUNhZwwuvWeTnu5ev2 +636: 5EYCAe5jLQhn6ofDSwQuD9nUqaDxA3pM7NWTVrcM7HfdMWqo +637: 5EYCAe5jLQhn6ofDSwRAxBL4x4u9cbvDr3Sy3oJBa7YMd9mJ +638: 5EYCAe5jLQhn6ofDSwRShCsf4ZaM5A26aiPUbjz22wR5tne4 +639: 5EYCAe5jLQhn6ofDSwRiSERFB4FYXi7yKPKz9gfrVmHpALrK +640: 5EYCAe5jLQhn6ofDSwRzBFxqHYvjzGDr44GVhdMgxbAYS1GD +641: 5EYCAe5jLQhn6ofDSwSFvHWRQ3bwSpKinjD1Fa3XRR3GhTgF +642: 5EYCAe5jLQhn6ofDSwSXfK41WYH8uNRbXQ9WoWjMtEuzyHBD +643: 5EYCAe5jLQhn6ofDSwSoQLbbd2xLMvXUG562MTRCM4njEg2N +644: 5EYCAe5jLQhn6ofDSwT59N9BjXdXpUdLzk2XuQ72otfTWSny +645: 5EYCAe5jLQhn6ofDSwTLtPgmr2JjH2jDjQy3TLnsGiYBn5Bi +646: 5EYCAe5jLQhn6ofDSwTcdREMxWyvjaq6U5uZ1HUhjYQv3fCb +647: 5EYCAe5jLQhn6ofDSwTtNSmx51f8C8vyCkr4ZEAYCNHeKPyY +648: 5EYCAe5jLQhn6ofDSwUA7UKYBWLKeh2qwRna7ArNfCANb6AU +649: 5EYCAe5jLQhn6ofDSwURrVs8J11X7F8ig6j5f7YD8236rSyk +650: 5EYCAe5jLQhn6ofDSwUhbXQiQVgiZoEbQmfbD4E3aquq87RN +651: 5EYCAe5jLQhn6ofDSwUyLYxJWzMv2MLU9Sc6kzut3fnZPti5 +652: 5EYCAe5jLQhn6ofDSwVF5aVtdV37UuSLt7YcJwbiWVfHfaaG +653: 5EYCAe5jLQhn6ofDSwVWpc3UjyiJwTYDcnV7rtHYyKY1w8Yy +654: 5EYCAe5jLQhn6ofDSwVnZdb4rUPWQ1e6MTRdQpyPS9QkCqGi +655: 5EYCAe5jLQhn6ofDSwW4Jf8exy4hrZjy68N8xmfDtyHUUStT +656: 5EYCAe5jLQhn6ofDSwWL3ggF5TjuK7qqpoJeWiM4MoACjq89 +657: 5EYCAe5jLQhn6ofDSwWbniDqBxR6mfwiZUFA4f2tpd2w1WS2 +658: 5EYCAe5jLQhn6ofDSwWsXjmRJT6JEE3bJ9BfcbijHSufH4xW +659: 5EYCAe5jLQhn6ofDSwX9GmK1QwmVgn9U2p8BAYQZkGnPYjux +660: 5EYCAe5jLQhn6ofDSwXR1nrbXSSh9LFLmV4giV6QD6f7pJFn +661: 5EYCAe5jLQhn6ofDSwXgkpQBdw7tbtMDWA1CGRnEfvXr5vs6 +662: 5EYCAe5jLQhn6ofDSwXxVqwmkRo64ST6EpwhpNU58kQaMqxk +663: 5EYCAe5jLQhn6ofDSwYEEsVMrvUHWzYxyVtDNK9ubaHJdUrm +664: 5EYCAe5jLQhn6ofDSwYVyu2wyR9UyYeqiApivFqk4QA2tzVu +665: 5EYCAe5jLQhn6ofDSwYmivaY5upgS6kiSqmEUCXaXE2mAc6w +666: 5EYCAe5jLQhn6ofDSwZ3Tx88CQVsterbBWhk29DQz3uVS7i8 +667: 5EYCAe5jLQhn6ofDSwZKCyfiJuB5MCxTvBeFa5uFSsnDhgGK +668: 5EYCAe5jLQhn6ofDSwZax1DJRPrGom4Leram82b5uhewyNoP +669: 5EYCAe5jLQhn6ofDSwZrh2ktXtXUGKADPXXGfyGvNXXgEyZ3 +670: 5EYCAe5jLQhn6ofDSwa8S4JUePCfisG68CTnDuxkqMQQWXvt +671: 5EYCAe5jLQhn6ofDSwaQB5r4ksssBRMxrsQHmrebJBH8nAcv +672: 5EYCAe5jLQhn6ofDSwafv7PesNZ4dyTqbYLoKoLRm19s3qJz +673: 5EYCAe5jLQhn6ofDSwawf8wEysEG6XZiLDHJsk2GDq2bKTmw +674: 5EYCAe5jLQhn6ofDSwbDQAUq6MuTZ5fb4tDpRgi6geuKbLxK +675: 5EYCAe5jLQhn6ofDSwbV9C2RCraf1dmToZAKydPw9Un3rxbC +676: 5EYCAe5jLQhn6ofDSwbktDa1KMFrUBsLYE6qXa5mcJen8ckd +677: 5EYCAe5jLQhn6ofDSwc2dF7bRqw3vjyDGu3M5Wmc58XWQBuK +678: 5EYCAe5jLQhn6ofDSwcJNGfBYLcFPJ561ZyrdTTSXxQEfmEu +679: 5EYCAe5jLQhn6ofDSwca7JCmeqHSqrAxkEvNBQ9GznGxwBdp +680: 5EYCAe5jLQhn6ofDSwcqrKkMmKxeJQGqUursjLq7Tc9hCorw +681: 5EYCAe5jLQhn6ofDSwd7bMHwspdqkxNiDaoPHHWwvS2RUdXJ +682: 5EYCAe5jLQhn6ofDSwdPLNqXzKK3DWUaxFjtqECnPFu9kC7N +683: 5EYCAe5jLQhn6ofDSwdf5QP86ozEg4aTgvgQPAtcr5mt1rjf +684: 5EYCAe5jLQhn6ofDSwdvpRviDJfS8cgLRbcuw7aTJuecHTjg +685: 5EYCAe5jLQhn6ofDSweCZTUJKoLdbAnDAGZRV4GHmjXLZCAK +686: 5EYCAe5jLQhn6ofDSweUJV1tSJ1q3it5twVw2zx8EZQ4pj72 +687: 5EYCAe5jLQhn6ofDSwek3WZUYnh2WGyxdcSSawdxhPGo6JxS +688: 5EYCAe5jLQhn6ofDSwf1nY74fHNDxq5qNHNx8tKoAD9XMwtS +689: 5EYCAe5jLQhn6ofDSwfHXZeemn3RRPBi6xKTgq1dd32FdSM8 +690: 5EYCAe5jLQhn6ofDSwfZGbCEtGicswHaqdFyEmhU5rtyu5Z6 +691: 5EYCAe5jLQhn6ofDSwfq1cjpzmPpLVPTaJCUniPJYgmiAiMS +692: 5EYCAe5jLQhn6ofDSwg6keHR7G51o3VLJy8zLf591WeSSbhJ +693: 5EYCAe5jLQhn6ofDSwgNVfq1DkkDFbbD3e5VtbkyULXAhwZq +694: 5EYCAe5jLQhn6ofDSwgeEhNbLFRQi9h5nK21SYSowAPtycbw +695: 5EYCAe5jLQhn6ofDSwguyivBSk6cAhnxWyxWzV8ePzGdFWrE +696: 5EYCAe5jLQhn6ofDSwhBikTmZEmodFtqFeu2YRpUrp9MX6zu +697: 5EYCAe5jLQhn6ofDSwhTTn1MfjT15ozhzKqY6NWKKe25nf5e +698: 5EYCAe5jLQhn6ofDSwhjCoYwnE8CYN6aizn3eKC9nTtp4KzB +699: 5EYCAe5jLQhn6ofDSwhzwq6XtioPzvCTTfiZCFszFHmYL1bG +700: 5EYCAe5jLQhn6ofDSwiGgre81DUbTUJLCLf4kCZpi7eGbazB +701: 5EYCAe5jLQhn6ofDSwiYRtBi7i9nv2QCw1baJ9FfAwWzrzNK +702: 5EYCAe5jLQhn6ofDSwipAujJECpzNaW5fgY5r5wVdmPj8dgE +703: 5EYCAe5jLQhn6ofDSwj5uwGtLhWBq8bxQMUbQ2dL6bGTQRjz +704: 5EYCAe5jLQhn6ofDSwjMexpUTCBPHghq92R6wyKAZR9Bg2zd +705: 5EYCAe5jLQhn6ofDSwjdPzN4ZgrakEohshMcVv112F1uwSaB +706: 5EYCAe5jLQhn6ofDSwju91uegBXnCnuacNJ83rgqV4teDK4S +707: 5EYCAe5jLQhn6ofDSwkAt3TEngCyfM1TM3EdboNfwtmNUvX2 +708: 5EYCAe5jLQhn6ofDSwkSd4zpuAtB7u7L5iB99k4WQie6kRBz +709: 5EYCAe5jLQhn6ofDSwkiN6YR1fZNaTDCpP7ehgkLsYWq238p +710: 5EYCAe5jLQhn6ofDSwkz78618AEa31K5Z44AFdSBLNPZHotQ +711: 5EYCAe5jLQhn6ofDSwmFr9dbEeumVZQxHizfoa81oCGHZWCA +712: 5EYCAe5jLQhn6ofDSwmXbBBBM9axx7Wq2PwBMWorG291q82P +713: 5EYCAe5jLQhn6ofDSwmoLCimTeGAQfchm4sguTVgir1k6n9U +714: 5EYCAe5jLQhn6ofDSwn55EGMa8wMsDiaVjpCTQBXBftUNKJq +715: 5EYCAe5jLQhn6ofDSwnLpFowgdcZKmpTEQki1LsMeVmCdpCj +716: 5EYCAe5jLQhn6ofDSwncZHMXo8HknKvKy5hDZHZC7KdvuXrB +717: 5EYCAe5jLQhn6ofDSwntJJu7ucxxEt2Chkdj7EF2a9WfB5ec +718: 5EYCAe5jLQhn6ofDSwoA3LSi27e9hS85SRaEfAvs2yPPSqde +719: 5EYCAe5jLQhn6ofDSwoRnMzJ8cKM9zDxB6WkD7chVoG7iPFH +720: 5EYCAe5jLQhn6ofDSwohXPXtF6zYcYKpumTFm4JXxd8qyujN +721: 5EYCAe5jLQhn6ofDSwoyGR5UMbfk56RheSPmJzzNRT1aFek4 +722: 5EYCAe5jLQhn6ofDSwpF1Sd4U6LwXeXaP7LGrwgCtGtJXFVq +723: 5EYCAe5jLQhn6ofDSwpWkUAeab28zCdT7nGnQtN3M6m2nvKc +724: 5EYCAe5jLQhn6ofDSwpnVViEh5hLSkjKrTDHxq3sovdm4Nw6 +725: 5EYCAe5jLQhn6ofDSwq4EXFpoaNXuJqCb89oWmjiGkWVLAto +726: 5EYCAe5jLQhn6ofDSwqKyYoQv53jMrw5Ko6K4iRYjaPDbs68 +727: 5EYCAe5jLQhn6ofDSwqbiaM12ZivpR2x4U2pcf7PCQFwsHxu +728: 5EYCAe5jLQhn6ofDSwqsTbtb94Q8Gy8po8yLAboDfE8g8qfu +729: 5EYCAe5jLQhn6ofDSwr9CdSBFZ5KjXEhXouqiYV4841QQmeD +730: 5EYCAe5jLQhn6ofDSwrQweymN3kXC5LaGUrMGVAtast8g9P8 +731: 5EYCAe5jLQhn6ofDSwrgggXMUYRiedST19nrpRrj3hkrwr4P +732: 5EYCAe5jLQhn6ofDSwrxRi4wb36v7BYKjpjNNNYZWXdbDbT2 +733: 5EYCAe5jLQhn6ofDSwsEAjcXhXn7ZjeCUVfsvKEPyMWKUy64 +734: 5EYCAe5jLQhn6ofDSwsVumA7p2TK2Hk5DAcPUFvESBP3kgYh +735: 5EYCAe5jLQhn6ofDSwsmenhhvX8WUqqwwqYu2Cc4u1Fn2KSS +736: 5EYCAe5jLQhn6ofDSwt3PpFJ31ohwPwpgWVQa9HuMq8WHtcH +737: 5EYCAe5jLQhn6ofDSwtK8qnt9WUuPx3hRBRv85yjpf1EZadQ +738: 5EYCAe5jLQhn6ofDSwtassLUG1A6rW9a9rNRg2faHUsxqMFi +739: 5EYCAe5jLQhn6ofDSwtrctt4NVqJK4FStXJwDyMQkJkh6s1F +740: 5EYCAe5jLQhn6ofDSwu8MvReUzWVmcMKdCFSmv3FD8dRNY1G +741: 5EYCAe5jLQhn6ofDSwuQ6wyEbVBhEATCMsBxKrj5fxW9dz3E +742: 5EYCAe5jLQhn6ofDSwufqyWphyrtgiZ56Y8TsoQv8nNsuu3k +743: 5EYCAe5jLQhn6ofDSwuwb14QpUY69GewqD4yRk6kbcFcBLhB +744: 5EYCAe5jLQhn6ofDSwvDL2bzvyDHbpkpZt1Uygnb4S8LT5bh +745: 5EYCAe5jLQhn6ofDSwvV549b3TtV4NrhJYwzXdURXG14ikbp +746: 5EYCAe5jLQhn6ofDSwvkp5hB9xZgWvxa3DtW5aAFz5snz8Jm +747: 5EYCAe5jLQhn6ofDSww2Z7EmGTEsyV4Smtq1dWr6SukXFvLY +748: 5EYCAe5jLQhn6ofDSwwJJ8nMNwv5S3AKWZmXBTXvujdFXSdM +749: 5EYCAe5jLQhn6ofDSwwa3AKwVSbGtbGCFEi2jQDmNZVyo8bB +750: 5EYCAe5jLQhn6ofDSwwqnBsXbwGUM9N4yueYHLubqPNi4em6 +751: 5EYCAe5jLQhn6ofDSwx7XDR7iRwfohTwiab3qHbSJDFSLPWB +752: 5EYCAe5jLQhn6ofDSwxPGExhpvcsGFZpTFXZPEHGm38Ac8CZ +753: 5EYCAe5jLQhn6ofDSwxf1GWHwRJ4iofhBvU4wAy7Drztsd4d +754: 5EYCAe5jLQhn6ofDSwxvkJ3t3uyGBMmZvbQaV7ewggsd9LGE +755: 5EYCAe5jLQhn6ofDSwyCVKbUAQeTdusSfGM634Ln9WkMQkR1 +756: 5EYCAe5jLQhn6ofDSwyUEM94GuKf6TyKPwHbb12ccLd5gYNT +757: 5EYCAe5jLQhn6ofDSwyjyNgePPzrZ25C8cE78wiT5AVowzRJ +758: 5EYCAe5jLQhn6ofDSwz1iQEEVtg41aB4sHAcgtQHXzNYDfiq +759: 5EYCAe5jLQhn6ofDSwzHTRmpcPMFU8Gwbx78Eq67zpFGVKAV +760: 5EYCAe5jLQhn6ofDSwzZCTKQit2SvgNpLd3dnmmxTe7zm2FX +761: 5EYCAe5jLQhn6ofDSwzpwUrzqNhePEUh5Hz9LiTnvTzj2o2S +762: 5EYCAe5jLQhn6ofDSx16gWQawsNqqnaZoxvetf9dPHsTJGVj +763: 5EYCAe5jLQhn6ofDSx1NRXxB4N43JLgSYdsASbqTr7kBZkMV +764: 5EYCAe5jLQhn6ofDSx1eAZVmArjEktnKHJofzYXJJwcuqZNN +765: 5EYCAe5jLQhn6ofDSx1uub3MHMQSDStC1ykBYVD8mmVe72B9 +766: 5EYCAe5jLQhn6ofDSx2BecawPr5dfzz4kegh6RtyEbNNNvFe +767: 5EYCAe5jLQhn6ofDSx2TPe8XWLkq8Z5wVKdCeNaohRF6eYof +768: 5EYCAe5jLQhn6ofDSvqFHR7HuaCvPkQxqZx8iHpeHQ8hVBKK +769: 5EYCAe5jLQhn6ofDSvqX2Set24t7rJWqaEteGEWUkE1RkrkR +770: 5EYCAe5jLQhn6ofDSvqnmUCU8ZZKJrciJuq9pBCKD3tA2LLb +771: 5EYCAe5jLQhn6ofDSvr4WVk4F4EWmQib3amfN7t9fsktJ77C +772: 5EYCAe5jLQhn6ofDSvrLFXHeMYuiDxpTnFiAv4Zz8hdcZbNr +773: 5EYCAe5jLQhn6ofDSvrbzYqEU3augWvLWvegU1FpbXWLqFRa +774: 5EYCAe5jLQhn6ofDSvrsjaNpaYG7952DFbbC1wwf4MP56tjt +775: 5EYCAe5jLQhn6ofDSvs9UbvQh2wJbd85zGXhZtdVXBFoNVtD +776: 5EYCAe5jLQhn6ofDSvsRDdTzoXcW4BDxiwUD7qKKz18Xe12H +777: 5EYCAe5jLQhn6ofDSvsgxf1av2HhWjKqTcQifn1ASq1FucFi +778: 5EYCAe5jLQhn6ofDSvsxhgZB2WxtyHRiCHMEDigzueszBXBe +779: 5EYCAe5jLQhn6ofDSvtESi6m91e6RqXavxHjmfNqNUkiT7mZ +780: 5EYCAe5jLQhn6ofDSvtWBjeMFWKHtPdTfdEFKc4fqJdSidEs +781: 5EYCAe5jLQhn6ofDSvtmvmBwMzzVLwjLQJAksYkWJ8WAzBPh +782: 5EYCAe5jLQhn6ofDSvu3fnjXUVfgoVqD8y7GRVSLkxNuFnUr +783: 5EYCAe5jLQhn6ofDSvuKQpH7azLtG3w5se3myS8BDnFdXVDQ +784: 5EYCAe5jLQhn6ofDSvub9qphhV25ic2xcJzHXNp1gc8MoHRr +785: 5EYCAe5jLQhn6ofDSvurtsNHoyhHBA8qLyvo5KVr9S164gKm +786: 5EYCAe5jLQhn6ofDSvv8dtusvUNUdiEi5esJdGBgcFspLGuj +787: 5EYCAe5jLQhn6ofDSvvQNvTU2y3g6GLapKopBCsX55kYc6uX +788: 5EYCAe5jLQhn6ofDSvvg7x149TisYpSTYzkKj9ZMXudGsZQv +789: 5EYCAe5jLQhn6ofDSvvwryYeFxQ51NYLHfgqH6FBzjW19P2E +790: 5EYCAe5jLQhn6ofDSvwDc16ENT5GTveD2LdLq2w2TZNjQxh2 +791: 5EYCAe5jLQhn6ofDSvwVM2dpUwkTvUk5m1ZrNycrvPFTgNTx +792: 5EYCAe5jLQhn6ofDSvwm64BQbSRfP2qxVgWMvvJhPD8BxAmh +793: 5EYCAe5jLQhn6ofDSvx2q5izhw6rqawqEMSsUrzXr2zvDq9o +794: 5EYCAe5jLQhn6ofDSvxJa7GapRn4J93hy2PP2ogNJrseVQgH +795: 5EYCAe5jLQhn6ofDSvxaK8pAvvTFkh9ahhKtakNCmgkNm9iv +796: 5EYCAe5jLQhn6ofDSvxr4AMm3R8TDFFTSNGQ8h43EWd72aAb +797: 5EYCAe5jLQhn6ofDSvy7oBuM9uoefoMLB3CugdjshLVqJHyr +798: 5EYCAe5jLQhn6ofDSvyPYDSwGQUr8MTCui9REaRiAANZa2Nj +799: 5EYCAe5jLQhn6ofDSvyfHEzXNuA3auZ5eP5vnX7YczFHqVq1 +800: 5EYCAe5jLQhn6ofDSvyw2GY7VPqF3TexP42SLToP5p826zpV +801: 5EYCAe5jLQhn6ofDSvzCmJ5hbtWSW1kq7ixwtQVDYdzkNx8G +802: 5EYCAe5jLQhn6ofDSvzUWKdHiPBdxZrhrPuTSMB41TsUeMmn +803: 5EYCAe5jLQhn6ofDSvzkFMAspsrqR7xab4qxzHrtUHkCuxdQ +804: 5EYCAe5jLQhn6ofDSw11zNiTwNY2sg4TKjnUYEYiw7cwBaW5 +805: 5EYCAe5jLQhn6ofDSw1HjQG43sDELEAL4Qiz6BEZPwVfTFoS +806: 5EYCAe5jLQhn6ofDSw1ZURoeAMtRnnGCo5fVe7vPrmNPiyE5 +807: 5EYCAe5jLQhn6ofDSw1qDTMEGrZdFLN5Xkc1C4cEKbF7zTVD +808: 5EYCAe5jLQhn6ofDSw26xUtpPMEphtTxGRYWk1J4nR7rGFA2 +809: 5EYCAe5jLQhn6ofDSw2NhWSQVqv2ASZq16V2HwyuFEzaXgBa +810: 5EYCAe5jLQhn6ofDSw2eSXyzcLbDczfhjmRXqtfji4sJoHqH +811: 5EYCAe5jLQhn6ofDSw2vBZXaiqGR5YmaUSN3PqMaAtk34tDS +812: 5EYCAe5jLQhn6ofDSw3Bvb5AqKwcY6sTD7JYwn3QdicmLfNX +813: 5EYCAe5jLQhn6ofDSw3TfcckwpcozeyKwnF4VijF6YVVcNh2 +814: 5EYCAe5jLQhn6ofDSw3jQeAM4KJ1TD5CgTBa3fR5ZNNDspJU +815: 5EYCAe5jLQhn6ofDSw419fhwAoyCumB5R885bc6v2CEx9X8a +816: 5EYCAe5jLQhn6ofDSw4GthFXHJeQNKGx9o4b9YnkV27gRHoX +817: 5EYCAe5jLQhn6ofDSw4Ydio7PoKbpsNptU16hVUawqzQgipw +818: 5EYCAe5jLQhn6ofDSw4pNkLhWHzoHRUhd8wcFSARQfs8xMi8 +819: 5EYCAe5jLQhn6ofDSw567mtHcnfzjyaaMot7oNrFsVjsE6KH +820: 5EYCAe5jLQhn6ofDSw5MroRsjHMCCXgT6UpdMKY6LKcbViXv +821: 5EYCAe5jLQhn6ofDSw5dbpyTqn2Pf5nKq9m8uGDvo9VKmA4Z +822: 5EYCAe5jLQhn6ofDSw5uLrX3xGhb7dtCZpheTCumFyN42vWo +823: 5EYCAe5jLQhn6ofDSw6B5t4e4mNnaBz5JVeA19bbioEnJXJY +824: 5EYCAe5jLQhn6ofDSw6SpucEBG3z2k5x3AafZ6HSBd7Wa7SR +825: 5EYCAe5jLQhn6ofDSw6iZw9pHkjBVJBpmqXB72yGeSzEqniD +826: 5EYCAe5jLQhn6ofDSw6zJxhQQFQNwrHhWWTgeyf77Gry7Sno +827: 5EYCAe5jLQhn6ofDSw7G3zEzWk5aQQPaFBQCCvLwa6jhP465 +828: 5EYCAe5jLQhn6ofDSw7Xo1nadEkmrxVSyrLhks2n2vcRefhC +829: 5EYCAe5jLQhn6ofDSw7oY3LAjjRyKWbKiXHDJoicVkV9vBPY +830: 5EYCAe5jLQhn6ofDSw85H4skrE7An4hCTCDirkQSxaMtBsPh +831: 5EYCAe5jLQhn6ofDSw8M26RLxinNEco5BsAEQh6HRQEcTSy1 +832: 5EYCAe5jLQhn6ofDSw8cm7xw5DTZhAtwvY6jxdn7tE7Lj4CV +833: 5EYCAe5jLQhn6ofDSw8tW9WXBi8m9izpfD3FWaTxM3z4ztxu +834: 5EYCAe5jLQhn6ofDSw9AFB47JCoxcH6hPsym4X9nosroGaQ6 +835: 5EYCAe5jLQhn6ofDSw9RzCbhQhVA4qCa8YvGcTqdGhjXY5dN +836: 5EYCAe5jLQhn6ofDSw9hjE9HXCAMXPJSsDrnAQXTjXcFomyC +837: 5EYCAe5jLQhn6ofDSw9yUFgsdgqYywQKbtoHiMDJCMUz5KLc +838: 5EYCAe5jLQhn6ofDSwAFDHETkBWkSVWCLZjoGHu8fBMiLqyN +839: 5EYCAe5jLQhn6ofDSwAWxJn3rgBwu3c55EgJpEay81EScYDv +840: 5EYCAe5jLQhn6ofDSwAnhLKdyAs9MbhwoucpNBGoaq7AtBND +841: 5EYCAe5jLQhn6ofDSwB4SMsE5fYLp9opYaZKv7xe3eyu9pB6 +842: 5EYCAe5jLQhn6ofDSwBLBPQpCADYGhuhHFVqU4eUWUrdRM7v +843: 5EYCAe5jLQhn6ofDSwBbvQxQJetjjG1a1vSM21LJyJjMhBbF +844: 5EYCAe5jLQhn6ofDSwBsfSVzR9ZwBp7SkbNrZx29S8c5xc5e +845: 5EYCAe5jLQhn6ofDSwC9QU3aXeF8eNDKVGKN7thytxUpEQ99 +846: 5EYCAe5jLQhn6ofDSwCR9VbAe8vL6vKCDwFsfqPpMnMYVzgn +847: 5EYCAe5jLQhn6ofDSwCgtX8kkdbXZUR4xcCPDn5epcEGmiXF +848: 5EYCAe5jLQhn6ofDSwCxdYgLs8Gj22WwhH8tmimVHS713CwC +849: 5EYCAe5jLQhn6ofDSwDENaDvycwvUacpRx5QKfTKkFyjJjj9 +850: 5EYCAe5jLQhn6ofDSwDW7bmX67d7w8ihAd1usc9AD5rTacmN +851: 5EYCAe5jLQhn6ofDSwDmrdK7CcJKPgpZuHxRRYpzfujBr41L +852: 5EYCAe5jLQhn6ofDSwE3berhK6yWrEvSdxtvyVWq8jbv7aHQ +853: 5EYCAe5jLQhn6ofDSwEKLgQHRbeiJo2KNdqSXSCfbZUePR9i +854: 5EYCAe5jLQhn6ofDSwEb5hwsY6KumM8C7Jmx5NtW4PMNeshT +855: 5EYCAe5jLQhn6ofDSwErpjVTeb17DuE4qyiTdKaLXDE6vTCK +856: 5EYCAe5jLQhn6ofDSwF8Zm33m5gJgTKwaeeyBGGAz36qCDCc +857: 5EYCAe5jLQhn6ofDSwFQJnadsaMW91RpKKbUjCx1SryZTqHp +858: 5EYCAe5jLQhn6ofDSwFg3p8Dz52hbZXh3zXzH9dqugrHjWf4 +859: 5EYCAe5jLQhn6ofDSwFwnqfp6Zhu47dZnfUVq6KgNWj219Be +860: 5EYCAe5jLQhn6ofDSwGDXsDQD4P6WfjSXLR1P31WqLbkGqnY +861: 5EYCAe5jLQhn6ofDSwGVGtkzKZ4HyDqKG1MWvyhMJAUUYEpB +862: 5EYCAe5jLQhn6ofDSwGm1vJaS3jVRmwBzgJ2UvPBkzMCoxJh +863: 5EYCAe5jLQhn6ofDSwH2kwrAYYQgtL34jMEY2s52DpDw5VNy +864: 5EYCAe5jLQhn6ofDSwHJVyPkf35tLt8wU2B3aokrge6fMCZn +865: 5EYCAe5jLQhn6ofDSwHaEzwLmXm5oSEpCh7Z8kSh9TyPctVW +866: 5EYCAe5jLQhn6ofDSwHqz2Uvt2SHFzLgwN44gh8XcHr7tZat +867: 5EYCAe5jLQhn6ofDSwJ7j42WzX7UiYSZg2zaEdpN57irABgV +868: 5EYCAe5jLQhn6ofDSwJPU5a771ngB6YSQhw5naWCXwbaReyd +869: 5EYCAe5jLQhn6ofDSwJfD77hDWTsdeeK9NsbLXC2zmUJhHzL +870: 5EYCAe5jLQhn6ofDSwJvx8fHL1956CkBt3p6tTssTbM2xpSz +871: 5EYCAe5jLQhn6ofDSwKChACsSVpGYkr4cikcSQZhvRDmEWT2 +872: 5EYCAe5jLQhn6ofDSwKUSBkTYzVU1JwwMPh7zMFYPF6VWKwG +873: 5EYCAe5jLQhn6ofDSwKkBDJ3fVAfTs3p64ddYHwNr4yDmodk +874: 5EYCAe5jLQhn6ofDSwL1vEqdmyqrvR9gpja96EdDJtqx3NjK +875: 5EYCAe5jLQhn6ofDSwLHfGPDtUX4NyFZZQWeeBK3miigK7b2 +876: 5EYCAe5jLQhn6ofDSwLZQHvozyCFqXMSJ5TAC7ztEYbQaawr +877: 5EYCAe5jLQhn6ofDSwLq9KUQ7TsTJ5TK2kPfk4gihNU8rKKM +878: 5EYCAe5jLQhn6ofDSwM6tM1zDxYekdZBmRLBJ1NZACLs7za8 +879: 5EYCAe5jLQhn6ofDSwMNdNZaLTDrDBf4W6Ggqx4Pd2DbPm1Z +880: 5EYCAe5jLQhn6ofDSwMeNQ7ASwu3fjkwEmDCPtkE5r6KfCqS +881: 5EYCAe5jLQhn6ofDSwMv7RekZSaF8HroyS9hwqS4Yfy3vs1i +882: 5EYCAe5jLQhn6ofDSwNBrTCLfwFSaqxgi76DVn7u1VqnCKdZ +883: 5EYCAe5jLQhn6ofDSwNTbUjvnRve3Q4ZSn2j3iojUKiWTxuR +884: 5EYCAe5jLQhn6ofDSwNjLWHWtvbqVxASBSyEbfVZw9bEjuGF +885: 5EYCAe5jLQhn6ofDSwP15Xq71RH2xWGJv7uk9cBQPyTy1KK2 +886: 5EYCAe5jLQhn6ofDSwPGpZNh7uxER4NBenrFhYsEroLhGv4U +887: 5EYCAe5jLQhn6ofDSwPYZavHEQdRscU4PTnmFVZ5KdDRYbDs +888: 5EYCAe5jLQhn6ofDSwPpJcTsLuJdLAZw88jGoSEunT69pCcM +889: 5EYCAe5jLQhn6ofDSwQ63e1TTPypniforofnMNvkFGxt5i9U +890: 5EYCAe5jLQhn6ofDSwQMnfZ3Ztf2FGmgbUcHuKcai6qcMaYL +891: 5EYCAe5jLQhn6ofDSwQdXh6dgPLDhpsZL9YoTGJRAviLdEmZ +892: 5EYCAe5jLQhn6ofDSwQuGieDnt1RANyS4pVK1CzFdkb4tgYN +893: 5EYCAe5jLQhn6ofDSwRB1kBouNgccw5JoVRpZ9g66aToALaq +894: 5EYCAe5jLQhn6ofDSwRSkmjQ1sMp5VBBYANL76MvZQLXS4Vu +895: 5EYCAe5jLQhn6ofDSwRiVoGz8N31Y3H4GqJqf33m2EDFhj5S +896: 5EYCAe5jLQhn6ofDSwRzEppaEriCzbNw1WFMCyjbV45yy81m +897: 5EYCAe5jLQhn6ofDSwSFyrNAMMPQT9UokBBrkvRRwsxiErwp +898: 5EYCAe5jLQhn6ofDSwSXisukTr4buhagUr8NJs7GQhqSWRPe +899: 5EYCAe5jLQhn6ofDSwSoTuTLaLjoNFgZDX4sroo6sXiAmzRT +900: 5EYCAe5jLQhn6ofDSwT5CvzvgqQzponRxC1PQkUwLMau3ePs +901: 5EYCAe5jLQhn6ofDSwTLwxYWoL6CHMtJgrwtxhAmoBTdKXyR +902: 5EYCAe5jLQhn6ofDSwTcgz66upmPjuzBRXtQWdrcG1LMazy6 +903: 5EYCAe5jLQhn6ofDSwTtS1dh2KSbCU64ACpv4aYSiqD5rdpF +904: 5EYCAe5jLQhn6ofDSwUAB3BH8p7nf2BvtsmRcXEHBf5p874L +905: 5EYCAe5jLQhn6ofDSwURv4isFJnz7aHodYhwATv7eUxYPt9r +906: 5EYCAe5jLQhn6ofDSwUhf6GTMoUBa8PgNDeSiQbx7JqGfSEd +907: 5EYCAe5jLQhn6ofDSwUyQ7p3UJ9P2gVZ6taxGMHna8hzw5fY +908: 5EYCAe5jLQhn6ofDSwVF99MdanpaVEbRqZXTpHyd2xajCotp +909: 5EYCAe5jLQhn6ofDSwVWtAuDhHVmwnhJaETyNEfTVnTTUJ62 +910: 5EYCAe5jLQhn6ofDSwVndCSoonAyQLoBJuQUvBMHxcLBjrJi +911: 5EYCAe5jLQhn6ofDSwW4NDzPvGrArtu43aLzU838RSCv1ehN +912: 5EYCAe5jLQhn6ofDSwWL7FXz2mXNKSzvnFHW24ixtG5eHAkV +913: 5EYCAe5jLQhn6ofDSwWbrH5a9GCZn16oWvE1a1QoM5xNYqL8 +914: 5EYCAe5jLQhn6ofDSwWsbJdAFksmEZCgFbAX7x6douq6pSNe +915: 5EYCAe5jLQhn6ofDSwX9LLAkNFYxh7JYzG72ftnUGjhq6ByT +916: 5EYCAe5jLQhn6ofDSwXR5MiLUkEA9fQRiw3YDqUJjZaZMp43 +917: 5EYCAe5jLQhn6ofDSwXgpPFvbEuMcDWJTbz3mnA9CPTHdVsC +918: 5EYCAe5jLQhn6ofDSwXxZQoWhjaZ4mcBCGvZKiqyfDL1u7hx +919: 5EYCAe5jLQhn6ofDSwYEJSM6pEFkXKi3vws4sfXp83CkAivU +920: 5EYCAe5jLQhn6ofDSwYW3TtgvivwysovfcoaRcDeas5USMYT +921: 5EYCAe5jLQhn6ofDSwYmnVSH3Dc9SRuoQHk5yYuV3gxChyyF +922: 5EYCAe5jLQhn6ofDSwZ3XWys9iHLtz1g8xgbXVbKWWpvydok +923: 5EYCAe5jLQhn6ofDSwZKGYXTGCxYMY7Ysdd75SH9yLhfFKGv +924: 5EYCAe5jLQhn6ofDSwZb1a53Nhdjp6DRcJZcdNxzSAaPWrbz +925: 5EYCAe5jLQhn6ofDSwZrkbcdVCJwGeKJLyW8BKeptzT7nFc5 +926: 5EYCAe5jLQhn6ofDSwa8VdADbgz8jCRB5eSdjGLfMpKr3te4 +927: 5EYCAe5jLQhn6ofDSwaQEehoiBfLBkX3pKP9HD2VpeCaKhrx +928: 5EYCAe5jLQhn6ofDSwafygFPpgLXeJcvYzKeq9iLHU5JbD23 +929: 5EYCAe5jLQhn6ofDSwawihnywB1j6rioHfGAP6QAkHx2rjpq +930: 5EYCAe5jLQhn6ofDSwbDTjLa3fgvZQpg2LCfw361D7pm8UxM +931: 5EYCAe5jLQhn6ofDSwbVCktAAAN81xvYm19BUymqfwhVQ2QH +932: 5EYCAe5jLQhn6ofDSwbkwnRkGf3KUX2RVg5h2vTg8maDfkCV +933: 5EYCAe5jLQhn6ofDSwc2goyLP9iWw58JEM2Cas9WbbSwwF7u +934: 5EYCAe5jLQhn6ofDSwcJRqWvVePiPdEAy1xi8oqM4RKgCyrk +935: 5EYCAe5jLQhn6ofDSwcaAs4Wc94urBL3hguDgkXBXFCQUa1R +936: 5EYCAe5jLQhn6ofDSwcqutc6idk7JjRvSMqjEhD1z558kNSY +937: 5EYCAe5jLQhn6ofDSwd7ev9gq8RJmHXoB2nEndtrStws24Jk +938: 5EYCAe5jLQhn6ofDSwdPPwhGwd6WDqdfuhikLaaguipbHhTc +939: 5EYCAe5jLQhn6ofDSwdf8yEs47mhgPjYeNfFtXGXNYhKZGZk +940: 5EYCAe5jLQhn6ofDSwdvsznTAcSu8wqRP3bmSTxMqNa3puJ5 +941: 5EYCAe5jLQhn6ofDSweCd2L3H786bVwJ7iYGzQeCJCSn6H8L +942: 5EYCAe5jLQhn6ofDSweUN3sdPboJ443ArPUnYML2m2KWNBKc +943: 5EYCAe5jLQhn6ofDSwek75RDW6UVWc93b4RJ6J1sDrCEdfCm +944: 5EYCAe5jLQhn6ofDSwf1r6xocb9gyAEvKjMoeEhhgg4xuJbG +945: 5EYCAe5jLQhn6ofDSwfHb8WPj5ptRiLo4QJKCBPY9VwhAwVR +946: 5EYCAe5jLQhn6ofDSwfZLA3yqaW5tGSfo5Epk85NcKpRSg1o +947: 5EYCAe5jLQhn6ofDSwfq5BbZx5BHLpYYXkBLJ4mD59h9iEEa +948: 5EYCAe5jLQhn6ofDSwg6pD9A4ZrUoNeRGR7qr1T3XyZsyiw8 +949: 5EYCAe5jLQhn6ofDSwgNZEgkB4XgFvkJ164MPx8szoScFak2 +950: 5EYCAe5jLQhn6ofDSwgeJGELHZCsiUrAjkzrwtpiTdKLXB4X +951: 5EYCAe5jLQhn6ofDSwgv3HmvQ3t5B2x3URwNVqWYvTC4naER +952: 5EYCAe5jLQhn6ofDSwhBnKKWWYZGdb3vD6st3nCPPH4o4Mat +953: 5EYCAe5jLQhn6ofDSwhTXLs6d3EU699nwmpPbitDr6wXL32D +954: 5EYCAe5jLQhn6ofDSwhjGNQgjXufYhFfgSku9fa4JvpFbgt4 +955: 5EYCAe5jLQhn6ofDSwi11PxGr2as1FMYR7hQhcFtmkgysGkc +956: 5EYCAe5jLQhn6ofDSwiGkRVrxXG4ToTR9ndvFYwjEaZi8ngw +957: 5EYCAe5jLQhn6ofDSwiYVT3T51wFvMZHtTaRoVdZhQSSQP4g +958: 5EYCAe5jLQhn6ofDSwipEUb3BWcTNufAd8WwMSKQAEKAg1NA +959: 5EYCAe5jLQhn6ofDSwj5yW8dJ1HeqTm3MoTSuP1Ed4BtwabB +960: 5EYCAe5jLQhn6ofDSwjMiXgDQVxrJ1rv6UPxTKh55t4dDCHY +961: 5EYCAe5jLQhn6ofDSwjdTZDoWze3kZxnq9LU1GNuYhwMUvSK +962: 5EYCAe5jLQhn6ofDSwjuCamPdVKFD84fZpGyZD4k1Xp5kfJk +963: 5EYCAe5jLQhn6ofDSwkAwcJyjyzSfgAYJVDV79kaUMgp2EPZ +964: 5EYCAe5jLQhn6ofDSwkSgdrZrUfe8EGR3A9zf6SQwBZYHmgP +965: 5EYCAe5jLQhn6ofDSwkiRfQ9xyLqanNHmq6WD38FQ1SGZTTQ +966: 5EYCAe5jLQhn6ofDSwkzAgwk5U233LUAWW31kyp5rqJzqBXR +967: 5EYCAe5jLQhn6ofDSwmFuiVLBxhEVta3FAyXJvVvKfBj6fFs +968: 5EYCAe5jLQhn6ofDSwmXek2vJTNRxSfuyqv2rsBknV4TNUaZ +969: 5EYCAe5jLQhn6ofDSwmoPmaWQx3dQzmniWrYQosbFJwBdpHQ +970: 5EYCAe5jLQhn6ofDSwn58o86XSipsYsfTBo3xkZRi8ouujZb +971: 5EYCAe5jLQhn6ofDSwnLspfgdwQ2L6yYBrjZWhFGAxgeBF8E +972: 5EYCAe5jLQhn6ofDSwnccrDGkS5Dnf5QvXg54dw6dnZNSred +973: 5EYCAe5jLQhn6ofDSwntMskrrvkRFDBHfCcacacw6cS6iMUZ +974: 5EYCAe5jLQhn6ofDSwoA6uJSyRRchmHAPsZ6AXJmZSJpzCSq +975: 5EYCAe5jLQhn6ofDSwoRqvr35v6pAKP38YVbiTzc2GBZFfwh +976: 5EYCAe5jLQhn6ofDSwohaxPdCQn1csUusDS7GQgSV64HXCQ1 +977: 5EYCAe5jLQhn6ofDSwoyKywDJuTD5RanbtNcpMNGwuw1npdK +978: 5EYCAe5jLQhn6ofDSwpF51UoRQ8QXygfLZK8NJ47Qjok4jZT +979: 5EYCAe5jLQhn6ofDSwpWp32PXtobzXnY5EFdvEjwsZgULCga +980: 5EYCAe5jLQhn6ofDSwpnZ4ZyePUoT5tQouC9UBRnLPZCbmdk +981: 5EYCAe5jLQhn6ofDSwq4J67Zkt9zudzHYa8f287coDRvsRGc +982: 5EYCAe5jLQhn6ofDSwqL37f9sNqCNC6AHF5Aa4oTG3Jf8xpw +983: 5EYCAe5jLQhn6ofDSwqbn9CjysWPpkC31v1g81VHisBPQptU +984: 5EYCAe5jLQhn6ofDSwqsXAkL6NBbHJHukaxBfxB8Bh47gAbt +985: 5EYCAe5jLQhn6ofDSwr9GCHvCrrnjrPnVFthDtrxeWvqx2sP +986: 5EYCAe5jLQhn6ofDSwrR1DqWKMXzCQVfDvqCmqYo7LoaDX1B +987: 5EYCAe5jLQhn6ofDSwrgkFP6RrDBexbXxbmiKnEdaAgJVGJY +988: 5EYCAe5jLQhn6ofDSwrxVGvgYLtP7WhQhGiDsivU2zZ2kvZ6 +989: 5EYCAe5jLQhn6ofDSwsEEJUGeqZaa4oHRwejRfcJVpRm2TYT +990: 5EYCAe5jLQhn6ofDSwsVyL1rmLEn2cuAAcbEycJ8xeJVJAsG +991: 5EYCAe5jLQhn6ofDSwsmiMZSspuyVB12uHXkXYyyRUBDZmPU +992: 5EYCAe5jLQhn6ofDSwt3TP72zKbAwj6udxUG5VfotJ3wqCyJ +993: 5EYCAe5jLQhn6ofDSwtKCQed6pGNQHCnNdQmdSMeM7vg76HA +994: 5EYCAe5jLQhn6ofDSwtawSCDDJwZrqJf7JMHBP3UowoQNX1a +995: 5EYCAe5jLQhn6ofDSwtrgTjoKocmKPQXqyHnjKjKGmg8eN7M +996: 5EYCAe5jLQhn6ofDSwu8RVHPSJHxmwWQaeEJHGR9jbYruht5 +997: 5EYCAe5jLQhn6ofDSwuQAWpyYnyAEVcHKKAoqD6zCRRbBXTx +998: 5EYCAe5jLQhn6ofDSwufuYNZfHeMh3iA3z7KP9npfFJKSy6v +999: 5EYCAe5jLQhn6ofDSwuweZv9mnKZ9bp2nf3pw6Uf85B3ia6x +1000: 5EYCAe5jLQhn6ofDSwvDPbTjtGzkc9uuXKzLV3AVau3mzD3F +1001: 5EYCAe5jLQhn6ofDSwvV8d1Kzmfx4i1nFzvr2yrL3ivWG1Wg +1002: 5EYCAe5jLQhn6ofDSwvkseYv7GM9XG7ezfsMavYAWYoEXUrg +1003: 5EYCAe5jLQhn6ofDSww2cg6WDm2LypDXjLos8sDzyNfxoEqD +1004: 5EYCAe5jLQhn6ofDSwwJMhe6LFhYSNKQU1kNgouqSCYh4mRE +1005: 5EYCAe5jLQhn6ofDSwwa6jBgSkNjtvRHCggtEkbfu2RRLWcA +1006: 5EYCAe5jLQhn6ofDSwwqqkjGZF3wMUX9wMdPnhHWMrJ9bwiU +1007: 5EYCAe5jLQhn6ofDSwx7anGrfjj8p2d2g2ZuLdyLpgAssiC4 +1008: 5EYCAe5jLQhn6ofDSwxPKopSnEQLGaiuQhWQtafBHW3c9VSf +1009: 5EYCAe5jLQhn6ofDSwxf4qN2tj5Xj8pn9NSvSXM1kKvLQtJU +1010: 5EYCAe5jLQhn6ofDSwxvorud1DkjBgvet3PRzU2rD9o4gWNR +1011: 5EYCAe5jLQhn6ofDSwyCYtTD7iRveF2XciKwYQigfyfnxDDr +1012: 5EYCAe5jLQhn6ofDSwyUHuzoED786o8QMPGT6MQX8oYXDznu +1013: 5EYCAe5jLQhn6ofDSwyk2wYPLhnKZMEH64CxeJ6MbdRFVYiN +1014: 5EYCAe5jLQhn6ofDSwz1my5yTCTX1uL9pj9UCEnC4THymGqt +1015: 5EYCAe5jLQhn6ofDSwzHWzdZZh8iUTS2ZQ5ykBU2XHAi2c5d +1016: 5EYCAe5jLQhn6ofDSwzZG2B9gBouw1XuJ52VJ89rz73SJLQt +1017: 5EYCAe5jLQhn6ofDSwzq13ijngV7PZdn2jxzr4qhSvvAZqXq +1018: 5EYCAe5jLQhn6ofDSx16k5GKuBAJr7jemQuWQ1XXukntqcmK +1019: 5EYCAe5jLQhn6ofDSx1NV6ov1fqWJfqXW5r1wxDNNafd76hY +1020: 5EYCAe5jLQhn6ofDSx1eE8MW8AWhmDwQEknXVtuCqQYMNwWU +1021: 5EYCAe5jLQhn6ofDSx1uy9u6EfBuDn3GyRj33qb3JER5eVd4 +1022: 5EYCAe5jLQhn6ofDSx2BiBSgM9s6gL99i6fYbnGsm4HovEUC +1023: 5EYCAe5jLQhn6ofDSx2TTCzGTeYJ8tF2Smc49ixiDtAYBtUX +1024: 5EYCAe5jLQhn6ofDSvqFLyy2rszPQ5a3o1vzDeCYos492Xug \ No newline at end of file diff --git a/eco-tests/src/helpers.rs b/eco-tests/src/helpers.rs index 5908590115..c6fa0ec72d 100644 --- a/eco-tests/src/helpers.rs +++ b/eco-tests/src/helpers.rs @@ -186,7 +186,7 @@ pub fn add_network_disable_subtoken(netuid: NetUid, tempo: u16, _modality: u16) pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost.into()); + add_balance_to_coldkey_account(coldkey, lock_cost.into()); TotalIssuance::::mutate(|total_issuance| { *total_issuance = total_issuance.saturating_add(lock_cost); }); @@ -205,7 +205,7 @@ pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { pub fn add_dynamic_network_without_emission_block(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost.into()); + add_balance_to_coldkey_account(coldkey, lock_cost.into()); TotalIssuance::::mutate(|total_issuance| { *total_issuance = total_issuance.saturating_add(lock_cost); }); @@ -299,7 +299,7 @@ pub fn increase_stake_on_coldkey_hotkey_account( netuid: NetUid, ) { // Ensure the coldkey has enough balance - SubtensorModule::add_balance_to_coldkey_account(coldkey, tao_staked.into()); + add_balance_to_coldkey_account(coldkey, tao_staked.into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(*coldkey), *hotkey, diff --git a/eco-tests/src/tests.rs b/eco-tests/src/tests.rs index 65a5a0cd0f..6c4dc4d10f 100644 --- a/eco-tests/src/tests.rs +++ b/eco-tests/src/tests.rs @@ -18,7 +18,7 @@ fn test_add_stake_ok_neuron_does_not_belong_to_coldkey() { let stake = DefaultMinStake::::get() * 10.into(); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&other_cold_key, stake.into()); + add_balance_to_coldkey_account(&other_cold_key, stake.into()); // Perform the request which is signed by a different cold key assert_ok!(SubtensorModule::add_stake( diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index 2596d80069..b5873f652d 100644 --- a/pallets/admin-utils/src/tests/mock.rs +++ b/pallets/admin-utils/src/tests/mock.rs @@ -157,6 +157,8 @@ parameter_types! { pub const LeaseDividendsDistributionInterval: u32 = 100; // 100 blocks pub const MaxImmuneUidsPercentage: Percent = Percent::from_percent(80); pub const EvmKeyAssociateRateLimit: u64 = 0; + pub const SubtensorPalletId: PalletId = PalletId(*b"subtensr"); + pub const BurnAccountId: PalletId = PalletId(*b"burntnsr"); } impl pallet_subtensor::Config for Test { @@ -232,6 +234,8 @@ impl pallet_subtensor::Config for Test { type CommitmentsInterface = CommitmentsI; type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit; type AuthorshipProvider = MockAuthorshipProvider; + type SubtensorPalletId = SubtensorPalletId; + type BurnAccountId = BurnAccountId; type WeightInfo = (); } @@ -529,10 +533,7 @@ pub fn register_ok_neuron( let bal = SubtensorModule::get_coldkey_balance(&coldkey_account_id); if bal < burn_u64 { - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - burn_u64 - bal + 10.into(), - ); + add_balance_to_coldkey_account(&coldkey_account_id, burn_u64 - bal + 10.into()); } let result = SubtensorModule::burned_register( @@ -570,3 +571,14 @@ pub fn step_block(n: u64) { let current: u64 = frame_system::Pallet::::block_number().into(); run_to_block(current + n); } + +#[allow(dead_code)] +pub fn add_balance_to_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao).unwrap(); +} + +#[allow(dead_code)] +pub fn remove_balance_from_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let _ = SubtensorModule::burn_tao(coldkey, tao); +} diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index a3c34f4dde..c5c1de3dd7 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -1260,7 +1260,7 @@ fn test_sudo_get_set_alpha() { pallet_subtensor::migrations::migrate_create_root_network::migrate_create_root_network::< Test, >(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000_u64.into()); assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey,)); // Should fail as signer does not own the subnet diff --git a/pallets/subtensor/rpc/src/lib.rs b/pallets/subtensor/rpc/src/lib.rs index 98e2df2f62..6feff774ad 100644 --- a/pallets/subtensor/rpc/src/lib.rs +++ b/pallets/subtensor/rpc/src/lib.rs @@ -109,6 +109,8 @@ pub trait SubtensorCustomApi { ) -> RpcResult>; #[method(name = "subnetInfo_getSubnetToPrune")] fn get_subnet_to_prune(&self, at: Option) -> RpcResult>; + #[method(name = "subnetInfo_getSubnetAccountId")] + fn get_subnet_account_id(&self, netuid: NetUid, at: Option) -> RpcResult>; } pub struct SubtensorCustom { @@ -531,4 +533,18 @@ where } } } + + fn get_subnet_account_id( + &self, + netuid: NetUid, + at: Option<::Hash>, + ) -> RpcResult> { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + match api.get_subnet_account_id(at, netuid) { + Ok(result) => Ok(result.encode()), + Err(_) => Err(Error::RuntimeError("Subnet does not exist".to_string()).into()), + } + } } diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index 84da95cd36..ece243e9cb 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -48,6 +48,7 @@ sp_api::decl_runtime_apis! { fn get_coldkey_auto_stake_hotkey(coldkey: AccountId32, netuid: NetUid) -> Option; fn get_selective_mechagraph(netuid: NetUid, subid: MechId, metagraph_indexes: Vec) -> Option>; fn get_subnet_to_prune() -> Option; + fn get_subnet_account_id(netuid: NetUid) -> Option; } pub trait StakeInfoRuntimeApi { diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 9a8fdac14d..c7438ffb94 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -43,6 +43,11 @@ mod pallet_benchmarks { TaoBalance::from(1_000_000) } + fn add_balance_to_coldkey_account(coldkey: &T::AccountId, tao: TaoBalance) { + let credit = Subtensor::::mint_tao(tao); + let _ = Subtensor::::spend_tao(coldkey, credit, tao).unwrap(); + } + /// This helper funds an account with: /// - 2x burn fee /// - 100x DefaultMinStake @@ -54,7 +59,7 @@ mod pallet_benchmarks { .saturating_mul(2.into()) .saturating_add(min_stake.saturating_mul(100.into())); - Subtensor::::add_balance_to_coldkey_account(who, deposit.into()); + add_balance_to_coldkey_account::(who, deposit.into()); } #[benchmark] @@ -168,7 +173,7 @@ mod pallet_benchmarks { let amount = TaoBalance::from(60_000_000); seed_swap_reserves::(netuid); - Subtensor::::add_balance_to_coldkey_account(&coldkey, total_stake.into()); + add_balance_to_coldkey_account::(&coldkey, total_stake.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -277,7 +282,7 @@ mod pallet_benchmarks { Subtensor::::set_burn(netuid, benchmark_registration_burn()); let amount: u64 = 1_000_000; - Subtensor::::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account::(&coldkey, amount.into()); #[extrinsic_call] _(RawOrigin::Signed(coldkey.clone()), netuid, hotkey.clone()); @@ -303,7 +308,7 @@ mod pallet_benchmarks { let amount: u64 = 100_000_000_000_000; seed_swap_reserves::(netuid); - Subtensor::::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account::(&coldkey, amount.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -323,7 +328,7 @@ mod pallet_benchmarks { Subtensor::::set_network_rate_limit(1); let amount: u64 = 100_000_000_000_000u64.saturating_mul(2); - Subtensor::::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account::(&coldkey, amount.into()); #[extrinsic_call] _(RawOrigin::Signed(coldkey.clone()), hotkey.clone()); @@ -479,7 +484,7 @@ mod pallet_benchmarks { let ed = ::ExistentialDeposit::get(); let swap_cost = Subtensor::::get_key_swap_cost(); - Subtensor::::add_balance_to_coldkey_account(&coldkey, swap_cost + ed); + add_balance_to_coldkey_account::(&coldkey, swap_cost + ed); #[extrinsic_call] _(RawOrigin::Signed(coldkey), new_coldkey_hash); @@ -549,7 +554,7 @@ mod pallet_benchmarks { hotkey1.clone(), )); - Subtensor::::add_balance_to_coldkey_account(&old_coldkey, free_balance_old); + add_balance_to_coldkey_account::(&old_coldkey, free_balance_old); let name: Vec = b"The fourth Coolest Identity".to_vec(); let identity = ChainIdentityV2 { name, @@ -828,7 +833,7 @@ mod pallet_benchmarks { let hotkey: T::AccountId = account("Alice", 0, seed); let initial_balance = TaoBalance::from(900_000_000_000_u64); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), initial_balance); + add_balance_to_coldkey_account::(&coldkey.clone(), initial_balance); let tao_reserve = TaoBalance::from(1_000_000_000_000_u64); let alpha_in = AlphaBalance::from(100_000_000_000_000_u64); @@ -875,7 +880,7 @@ mod pallet_benchmarks { let burn_fee = Subtensor::::get_burn(netuid); let stake_tao = DefaultMinStake::::get().saturating_mul(10.into()); let deposit = burn_fee.saturating_mul(2.into()).saturating_add(stake_tao); - Subtensor::::add_balance_to_coldkey_account(&coldkey, deposit.into()); + add_balance_to_coldkey_account::(&coldkey, deposit.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -898,7 +903,7 @@ mod pallet_benchmarks { let alpha_to_move = Subtensor::::get_stake_for_hotkey_and_coldkey_on_subnet(&origin, &coldkey, netuid); - Subtensor::::create_account_if_non_existent(&coldkey, &destination); + let _ = Subtensor::::create_account_if_non_existent(&coldkey, &destination); StakingOperationRateLimiter::::remove((origin.clone(), coldkey.clone(), netuid)); @@ -937,7 +942,7 @@ mod pallet_benchmarks { set_reserves::(netuid, tao_reserve, alpha_in); let wallet_bal = 1000000u32.into(); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), wallet_bal); + add_balance_to_coldkey_account::(&coldkey.clone(), wallet_bal); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -946,7 +951,7 @@ mod pallet_benchmarks { )); let staked_amt = TaoBalance::from(100_000_000_000_u64); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), staked_amt); + add_balance_to_coldkey_account::(&coldkey.clone(), staked_amt); assert_ok!(Subtensor::::add_stake( RawOrigin::Signed(coldkey.clone()).into(), @@ -1004,7 +1009,7 @@ mod pallet_benchmarks { let limit_swap = TaoBalance::from(1_000_000_000_u64); let amount_to_be_staked = TaoBalance::from(440_000_000_000_u64); let amount_swapped = AlphaBalance::from(30_000_000_000_u64); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amount); + add_balance_to_coldkey_account::(&coldkey.clone(), amount); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1054,7 +1059,7 @@ mod pallet_benchmarks { let reg_fee = Subtensor::::get_burn(netuid); let stake_tao = DefaultMinStake::::get().saturating_mul(10.into()); let deposit = reg_fee.saturating_mul(2.into()).saturating_add(stake_tao); - Subtensor::::add_balance_to_coldkey_account(&coldkey, deposit.into()); + add_balance_to_coldkey_account::(&coldkey, deposit.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1077,7 +1082,7 @@ mod pallet_benchmarks { let alpha_to_transfer = Subtensor::::get_stake_for_hotkey_and_coldkey_on_subnet(&hot, &coldkey, netuid); - Subtensor::::create_account_if_non_existent(&dest, &hot); + let _ = Subtensor::::create_account_if_non_existent(&dest, &hot); StakingOperationRateLimiter::::remove((hot.clone(), coldkey.clone(), netuid)); @@ -1110,7 +1115,7 @@ mod pallet_benchmarks { let reg_fee = Subtensor::::get_burn(netuid1); let stake_tao = DefaultMinStake::::get().saturating_mul(10.into()); let deposit = reg_fee.saturating_mul(2.into()).saturating_add(stake_tao); - Subtensor::::add_balance_to_coldkey_account(&coldkey, deposit.into()); + add_balance_to_coldkey_account::(&coldkey, deposit.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1262,7 +1267,7 @@ mod pallet_benchmarks { Subtensor::::set_network_registration_allowed(1.into(), true); Subtensor::::set_network_rate_limit(1); let amount: u64 = 9_999_999_999_999; - Subtensor::::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account::(&coldkey, amount.into()); #[extrinsic_call] _( @@ -1327,7 +1332,7 @@ mod pallet_benchmarks { let descr = vec![]; let add = vec![]; - Subtensor::::create_account_if_non_existent(&coldkey, &hotkey); + let _ = Subtensor::::create_account_if_non_existent(&coldkey, &hotkey); Subtensor::::init_new_network(netuid, 1); Subtensor::::set_network_registration_allowed(netuid, true); SubtokenEnabled::::insert(netuid, true); @@ -1335,7 +1340,7 @@ mod pallet_benchmarks { seed_swap_reserves::(netuid); let deposit: u64 = 1_000_000_000u64.saturating_mul(2); - Subtensor::::add_balance_to_coldkey_account(&coldkey, deposit.into()); + add_balance_to_coldkey_account::(&coldkey, deposit.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1403,7 +1408,7 @@ mod pallet_benchmarks { let reg_balance = TaoBalance::from(1_000_000_u64); seed_swap_reserves::(netuid); - Subtensor::::add_balance_to_coldkey_account(&coldkey, reg_balance.into()); + add_balance_to_coldkey_account::(&coldkey, reg_balance.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1423,7 +1428,7 @@ mod pallet_benchmarks { Owner::::insert(&old, &coldkey); let cost = Subtensor::::get_key_swap_cost(); - Subtensor::::add_balance_to_coldkey_account(&coldkey, cost.into()); + add_balance_to_coldkey_account::(&coldkey, cost.into()); #[extrinsic_call] _(RawOrigin::Signed(coldkey.clone()), old, new, None); @@ -1442,7 +1447,7 @@ mod pallet_benchmarks { fn unstake_all() { let coldkey: T::AccountId = whitelisted_caller(); let hotkey: T::AccountId = account("A", 0, 14); - Subtensor::::create_account_if_non_existent(&coldkey, &hotkey); + let _ = Subtensor::::create_account_if_non_existent(&coldkey, &hotkey); #[extrinsic_call] _(RawOrigin::Signed(coldkey.clone()), hotkey); @@ -1471,7 +1476,7 @@ mod pallet_benchmarks { AlphaBalance::from(100_000_000_000_u64), ); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 1000000u32.into()); + add_balance_to_coldkey_account::(&coldkey.clone(), 1000000u32.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1480,7 +1485,7 @@ mod pallet_benchmarks { )); let staked_amt = TaoBalance::from(100_000_000_000_u64); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), staked_amt); + add_balance_to_coldkey_account::(&coldkey.clone(), staked_amt); assert_ok!(Subtensor::::add_stake( RawOrigin::Signed(coldkey.clone()).into(), @@ -1519,7 +1524,7 @@ mod pallet_benchmarks { set_reserves::(netuid, tao_reserve, alpha_in); let wallet_bal = 1000000u32.into(); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), wallet_bal); + add_balance_to_coldkey_account::(&coldkey.clone(), wallet_bal); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1535,7 +1540,7 @@ mod pallet_benchmarks { .saturating_to_num::() .into(); let staked_amt = TaoBalance::from(1_000_000_000_u64); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), staked_amt); + add_balance_to_coldkey_account::(&coldkey.clone(), staked_amt); assert_ok!(Subtensor::::add_stake( RawOrigin::Signed(coldkey.clone()).into(), @@ -1566,7 +1571,7 @@ mod pallet_benchmarks { let cap = TaoBalance::from(2_000_000_000_000_u64); // 2000 TAO let funds_account: T::AccountId = account("funds", 0, 0); - Subtensor::::add_balance_to_coldkey_account(&funds_account, cap.into()); + add_balance_to_coldkey_account::(&funds_account, cap.into()); pallet_crowdloan::Crowdloans::::insert( crowdloan_id, @@ -1625,7 +1630,7 @@ mod pallet_benchmarks { let cap = TaoBalance::from(2_000_000_000_000_u64); // 2000 TAO let funds_account: T::AccountId = account("funds", 0, 0); - Subtensor::::add_balance_to_coldkey_account(&funds_account, cap); + add_balance_to_coldkey_account::(&funds_account, cap); pallet_crowdloan::Crowdloans::::insert( crowdloan_id, @@ -1670,7 +1675,7 @@ mod pallet_benchmarks { let lease_id = 0; let lease = SubnetLeases::::get(0).unwrap(); let hotkey = account::("beneficiary_hotkey", 0, 0); - Subtensor::::create_account_if_non_existent(&beneficiary, &hotkey); + let _ = Subtensor::::create_account_if_non_existent(&beneficiary, &hotkey); #[extrinsic_call] _( @@ -1752,7 +1757,7 @@ mod pallet_benchmarks { Subtensor::::set_network_registration_allowed(netuid, true); let amount = 900_000_000_000u64; - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amount.into()); + add_balance_to_coldkey_account::(&coldkey.clone(), amount.into()); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), @@ -1780,7 +1785,7 @@ mod pallet_benchmarks { let netuid = Subtensor::::get_next_netuid(); let lock_cost = Subtensor::::get_network_lock_cost(); - Subtensor::::add_balance_to_coldkey_account(&coldkey, lock_cost.into()); + add_balance_to_coldkey_account::(&coldkey, lock_cost.into()); assert_ok!(Subtensor::::register_network( RawOrigin::Signed(coldkey.clone()).into(), @@ -1854,7 +1859,7 @@ mod pallet_benchmarks { let netuid = Subtensor::::get_next_netuid(); let lock_cost = Subtensor::::get_network_lock_cost(); - Subtensor::::add_balance_to_coldkey_account(&coldkey, lock_cost.into()); + add_balance_to_coldkey_account::(&coldkey, lock_cost.into()); assert_ok!(Subtensor::::register_network( RawOrigin::Signed(coldkey.clone()).into(), @@ -1885,7 +1890,7 @@ mod pallet_benchmarks { let balance_update = TaoBalance::from(900_000_000_000_u64); let limit = TaoBalance::from(6_000_000_000_u64); let amount = TaoBalance::from(44_000_000_000_u64); - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), balance_update); + add_balance_to_coldkey_account::(&coldkey.clone(), balance_update); let tao_reserve = TaoBalance::from(150_000_000_000_u64); let alpha_in = AlphaBalance::from(100_000_000_000_u64); diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index 20dc9c5e6f..a5647e5e61 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -70,7 +70,7 @@ impl Pallet { pub fn root_proportion(netuid: NetUid) -> U96F32 { let alpha_issuance = U96F32::from_num(Self::get_alpha_issuance(netuid)); - let root_tao: U96F32 = U96F32::from_num(SubnetTAO::::get(NetUid::ROOT)); + let root_tao: U96F32 = U96F32::from_num(Self::get_subnet_tao(NetUid::ROOT)); let tao_weight: U96F32 = root_tao.saturating_mul(Self::get_tao_weight()); let root_proportion: U96F32 = tao_weight diff --git a/pallets/subtensor/src/coinbase/mod.rs b/pallets/subtensor/src/coinbase/mod.rs index 8d06228593..a5475674a7 100644 --- a/pallets/subtensor/src/coinbase/mod.rs +++ b/pallets/subtensor/src/coinbase/mod.rs @@ -5,3 +5,4 @@ pub mod reveal_commits; pub mod root; pub mod run_coinbase; pub mod subnet_emissions; +pub mod tao; diff --git a/pallets/subtensor/src/coinbase/root.rs b/pallets/subtensor/src/coinbase/root.rs index 53b49a51ec..032002bf95 100644 --- a/pallets/subtensor/src/coinbase/root.rs +++ b/pallets/subtensor/src/coinbase/root.rs @@ -110,7 +110,7 @@ impl Pallet { ); // --- 6. Create a network account for the user if it doesn't exist. - Self::create_account_if_non_existent(&coldkey, &hotkey); + Self::create_account_if_non_existent(&coldkey, &hotkey)?; // --- 7. Fetch the current size of the subnetwork. let current_num_root_validators: u16 = Self::get_num_root_validators(); diff --git a/pallets/subtensor/src/coinbase/tao.rs b/pallets/subtensor/src/coinbase/tao.rs new file mode 100644 index 0000000000..8cbe19c3da --- /dev/null +++ b/pallets/subtensor/src/coinbase/tao.rs @@ -0,0 +1,305 @@ +/// This file contains all critical operations with TAO and Alpha: +/// +/// - Minting, burning, recycling, and transferring +/// - Reading colkey TAO balances +/// - Access to subnet TAO reserves +/// +use frame_support::traits::{ + Imbalance, + fungible::Mutate, + tokens::{ + Fortitude, Precision, Preservation, + fungible::{Balanced, Credit, Inspect}, + }, +}; +use sp_runtime::traits::AccountIdConversion; +use sp_runtime::{DispatchError, DispatchResult}; +use subtensor_runtime_common::{NetUid, TaoBalance}; + +use super::*; + +pub type BalanceOf = + <::Currency as fungible::Inspect<::AccountId>>::Balance; + +pub type CreditOf = Credit<::AccountId, ::Currency>; + +pub const MAX_TAO_ISSUANCE: u64 = 21_000_000_000_000_000_u64; + +impl Pallet { + /// Returns Subnet TAO reserve using SubnetTAO map. + /// Do not use subnet account balance because it may also contain + /// locked TAO. + pub fn get_subnet_tao(netuid: NetUid) -> TaoBalance { + SubnetTAO::::get(netuid) + } + + /// Transfer TAO from one coldkey account to another. + /// + /// This is a plain transfer and may reap the origin account if `amount` reduces + /// its balance below the existential deposit (ED). + pub fn transfer_tao( + origin_coldkey: &T::AccountId, + destination_coldkey: &T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let max_transferrable = ::Currency::reducible_balance( + origin_coldkey, + Preservation::Expendable, + Fortitude::Polite, + ); + + ensure!(amount <= max_transferrable, Error::::InsufficientBalance); + + // If remainder drops below ED, then account is killed, balance is lost, and we + // need to reduce total issuance + let remainder = max_transferrable.saturating_sub(amount); + if remainder < ::Currency::minimum_balance() { + // Decrease subtensor pallet total issuance + TotalIssuance::::mutate(|total| { + *total = total.saturating_sub(remainder); + }); + } + + ::Currency::transfer( + origin_coldkey, + destination_coldkey, + amount, + Preservation::Expendable, + )?; + Ok(()) + } + + /// Transfer all transferable TAO from `origin_coldkey` to `destination_coldkey`, + /// allowing the origin account to be reaped. + /// + /// # Parameters + /// - `origin_coldkey`: Source account. + /// - `destination_coldkey`: Destination account. + /// + /// # Returns + /// DispatchResult of the operation. + /// + /// # Errors + /// - [`Error::::InsufficientBalance`] if there is no transferable balance. + /// - Any error returned by the underlying currency transfer. + pub fn transfer_all_tao_and_kill( + origin_coldkey: &T::AccountId, + destination_coldkey: &T::AccountId, + ) -> DispatchResult { + let amount_to_transfer = ::Currency::reducible_balance( + origin_coldkey, + Preservation::Expendable, + Fortitude::Polite, + ); + + if !amount_to_transfer.is_zero() { + ::Currency::transfer( + origin_coldkey, + destination_coldkey, + amount_to_transfer, + Preservation::Expendable, + )?; + } + + Ok(()) + } + + /// Transfer TAO from a coldkey account for staking. + /// + /// If transferring the full `amount` would reap the origin account, this + /// function leaves the existential deposit (ED) in place and transfers less. + /// + /// # Parameters + /// - `netuid`: Subnet identifier. + /// - `origin_coldkey`: Account to transfer TAO from. + /// - `destination_coldkey`: Account to transfer TAO to. + /// - `amount`: Requested amount to transfer. + /// + /// # Returns + /// Returns the actual amount transferred. + /// + /// # Errors + /// Returns [`Error::::InsufficientBalance`] if no positive amount can be + /// transferred while preserving the origin account. + /// + /// Propagates any other transfer error from the underlying currency. + pub fn transfer_tao_to_subnet( + netuid: NetUid, + origin_coldkey: &T::AccountId, + amount: BalanceOf, + ) -> Result, DispatchError> { + if amount.is_zero() { + return Ok(0.into()); + } + + let subnet_account: T::AccountId = + Self::get_subnet_account_id(netuid).ok_or(Error::::SubnetNotExists)?; + + let max_preserving_amount = ::Currency::reducible_balance( + origin_coldkey, + Preservation::Preserve, + Fortitude::Polite, + ); + + let amount_to_transfer = amount.min(max_preserving_amount); + + ensure!( + !amount_to_transfer.is_zero(), + Error::::InsufficientBalance + ); + + ::Currency::transfer( + origin_coldkey, + &subnet_account, + amount_to_transfer, + Preservation::Preserve, + )?; + + Ok(amount_to_transfer) + } + + /// Move unstaked TAO from subnet account to coldkey. + pub fn transfer_tao_from_subnet( + netuid: NetUid, + coldkey: &T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let subnet_account: T::AccountId = + Self::get_subnet_account_id(netuid).ok_or(Error::::SubnetNotExists)?; + Self::transfer_tao(&subnet_account, coldkey, amount) + } + + /// Permanently remove TAO amount from existence by moving to the burn + /// address. Does not effect issuance rate + pub fn burn_tao(coldkey: &T::AccountId, amount: BalanceOf) -> DispatchResult { + let burn_address: T::AccountId = T::BurnAccountId::get().into_account_truncating(); + Self::transfer_tao(coldkey, &burn_address, amount)?; + Ok(()) + } + + /// Remove TAO from existence and reduce total issuance. + /// Effects issuance rate by reducing TI. + pub fn recycle_tao(coldkey: &T::AccountId, amount: BalanceOf) -> DispatchResult { + // Ensure that the coldkey doesn't drop below ED + let max_preserving_amount = ::Currency::reducible_balance( + coldkey, + Preservation::Preserve, + Fortitude::Polite, + ); + ensure!( + amount <= max_preserving_amount, + Error::::InsufficientBalance + ); + + // Decrease subtensor pallet total issuance + TotalIssuance::::mutate(|total| { + *total = total.saturating_sub(amount); + }); + + let _ = ::Currency::withdraw( + coldkey, + amount, + Precision::Exact, + Preservation::Expendable, + Fortitude::Force, + ) + .map_err(|_| Error::::BalanceWithdrawalError)? + .peek(); + + Ok(()) + } + + pub fn can_remove_balance_from_coldkey_account( + coldkey: &T::AccountId, + amount: BalanceOf, + ) -> bool { + amount <= Self::get_coldkey_balance(coldkey) + } + + pub fn get_coldkey_balance(coldkey: &T::AccountId) -> BalanceOf { + ::Currency::reducible_balance( + coldkey, + Preservation::Expendable, + Fortitude::Polite, + ) + } + + /// Create TAO and return the imbalance. + /// + /// The mint workflow is following: + /// 1. mint_tao in block_emission + /// 2. spend_tao in run_coinbase (distribute to subnets) + /// 3. None should be left, so burn the remainder using burn_credit for records + pub fn mint_tao(amount: BalanceOf) -> CreditOf { + // Hard-limit maximum issuance to 21M TAO. Never issue more. + let current_issuance = ::Currency::total_issuance(); + + let remaining_issuance = + TaoBalance::from(MAX_TAO_ISSUANCE).saturating_sub(current_issuance); + let amount_to_issue = amount.min(remaining_issuance); + + // Increase subtensor pallet total issuance + TotalIssuance::::mutate(|total| { + *total = total.saturating_add(amount_to_issue); + }); + + ::Currency::issue(amount_to_issue) + } + + /// Spend part of the imbalance + /// The part parameter is the balance itself that will be credited to the coldkey + /// Return the remaining credit or error + pub fn spend_tao( + coldkey: &T::AccountId, + credit: CreditOf, + part: BalanceOf, + ) -> Result, DispatchError> { + let (to_spend, remainder) = credit.split(part); + + ::Currency::resolve(coldkey, to_spend) + .map_err(|_credit| DispatchError::Other("Could not resolve partial credit"))?; + + Ok(remainder) + } + + /// Finalizes the unused part of the minted TAO. Normally, there should be none, this function + /// is only needed for guarding / logging + pub fn burn_credit(credit: CreditOf) -> DispatchResult { + let amount = credit.peek(); + if amount.is_zero() { + // Normal behavior + return Ok(()); + } + + // Some credit is remaining. This is error and it should be corrected. Record the situation with + // burned amount in logs and in burn_address. + let burn_address: T::AccountId = T::BurnAccountId::get().into_account_truncating(); + log::error!( + "burn_credit received non-zero credit ({:?}); sending it to burn account {:?}, which will burn it", + amount, + burn_address, + ); + + ::Currency::resolve(&burn_address, credit).map_err(|unresolved_credit| { + log::error!( + "burn_credit failed: could not resolve credit {:?} into burn account {:?}", + unresolved_credit.peek(), + burn_address, + ); + DispatchError::Other("Could not resolve burn credit") + }) + } + + // pub fn drain_tao_imbalance_into_subnet_reserve(imbalance: NegativeImbalance, netuid: NetUid) { + // } + + // pub fn mint_tao_for_subnet_reserve(tao: TaoBalance, netuid: NetUid) -> DispatchResult { + // let maybe_subnet_account = SubtensorModule::get_subnet_account_id(netuid); + // if let Some(subnet_account) = maybe_subnet_account { + // let _ = ::Currency::deposit(subnet_account, tao, Precision::BestEffort); + // Ok(()) + // } else { + // Err(Error::::SubnetNotExists) + // } + // } +} diff --git a/pallets/subtensor/src/guards/check_coldkey_swap.rs b/pallets/subtensor/src/guards/check_coldkey_swap.rs index 730b694bee..14b1a25ac9 100644 --- a/pallets/subtensor/src/guards/check_coldkey_swap.rs +++ b/pallets/subtensor/src/guards/check_coldkey_swap.rs @@ -88,7 +88,7 @@ mod tests { use pallet_subtensor_proxy::Call as ProxyCall; use sp_core::U256; use sp_runtime::traits::{Dispatchable, Hash}; - use subtensor_runtime_common::ProxyType; + use subtensor_runtime_common::{ProxyType, TaoBalance}; type HashingOf = ::Hashing; @@ -149,6 +149,11 @@ mod tests { RuntimeCall::System(SystemCall::remark { remark: vec![] }) } + fn add_balance_to_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao).unwrap(); + } + #[test] fn no_active_swap_allows_calls() { new_test_ext(1).execute_with(|| { @@ -241,8 +246,8 @@ mod tests { ColdkeySwapAnnouncements::::insert(real, (now, hash)); // Give delegate enough balance for proxy deposit - SubtensorModule::add_balance_to_coldkey_account(&real, 1_000_000_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&delegate, 1_000_000_000.into()); + add_balance_to_coldkey_account(&real, 1_000_000_000.into()); + add_balance_to_coldkey_account(&delegate, 1_000_000_000.into()); // Register proxy: delegate can act on behalf of real assert_ok!(Proxy::add_proxy( @@ -280,9 +285,9 @@ mod tests { let hash = HashingOf::::hash_of(&U256::from(42)); ColdkeySwapAnnouncements::::insert(real, (now, hash)); - SubtensorModule::add_balance_to_coldkey_account(&real, 1_000_000_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&delegate1, 1_000_000_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&delegate2, 1_000_000_000.into()); + add_balance_to_coldkey_account(&real, 1_000_000_000.into()); + add_balance_to_coldkey_account(&delegate1, 1_000_000_000.into()); + add_balance_to_coldkey_account(&delegate2, 1_000_000_000.into()); // delegate1 can proxy for real, delegate2 can proxy for delegate1 assert_ok!(Proxy::add_proxy( diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 454c1d01b4..b78c960b48 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -2656,17 +2656,6 @@ impl> Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid) } - fn increase_balance(coldkey: &T::AccountId, tao: TaoBalance) { - Self::add_balance_to_coldkey_account(coldkey, tao.into()) - } - - fn decrease_balance( - coldkey: &T::AccountId, - tao: TaoBalance, - ) -> Result { - Self::remove_balance_from_coldkey_account(coldkey, tao.into()) - } - fn increase_stake( coldkey: &T::AccountId, hotkey: &T::AccountId, diff --git a/pallets/subtensor/src/macros/config.rs b/pallets/subtensor/src/macros/config.rs index b3da63e437..12623d5632 100644 --- a/pallets/subtensor/src/macros/config.rs +++ b/pallets/subtensor/src/macros/config.rs @@ -7,6 +7,7 @@ use frame_support::pallet_macros::pallet_section; mod config { use crate::{CommitmentsInterface, GetAlphaForTao, GetTaoForAlpha}; + use frame_support::PalletId; use pallet_commitments::GetCommitments; use subtensor_runtime_common::AuthorshipInfo; use subtensor_swap_interface::{SwapEngine, SwapHandler}; @@ -256,5 +257,11 @@ mod config { /// Maximum percentage of immune UIDs. #[pallet::constant] type MaxImmuneUidsPercentage: Get; + /// Pallet account ID + #[pallet::constant] + type SubtensorPalletId: Get; + /// Burn account ID + #[pallet::constant] + type BurnAccountId: Get; } } diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index aa5ca6ee98..6c3bed4ada 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1081,7 +1081,7 @@ mod dispatches { ) -> DispatchResult { ensure_root(origin)?; - if swap_cost.to_u64() > 0 { + if !swap_cost.is_zero() { Self::charge_swap_cost(&old_coldkey, swap_cost)?; } Self::do_swap_coldkey(&old_coldkey, &new_coldkey)?; @@ -1778,7 +1778,7 @@ mod dispatches { pub fn try_associate_hotkey(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { let coldkey = ensure_signed(origin)?; - let _ = Self::do_try_associate_hotkey(&coldkey, &hotkey); + Self::do_try_associate_hotkey(&coldkey, &hotkey)?; Ok(()) } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 8bec922058..7013156f63 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -172,7 +172,9 @@ mod hooks { // Migrate fix bad hk swap .saturating_add(migrations::migrate_fix_bad_hk_swap::migrate_fix_bad_hk_swap::()) // Fix RootClaimed overclaim caused by single-subnet hotkey swap bug - .saturating_add(migrations::migrate_fix_root_claimed_overclaim::migrate_fix_root_claimed_overclaim::()); + .saturating_add(migrations::migrate_fix_root_claimed_overclaim::migrate_fix_root_claimed_overclaim::()) + // Mint missing SubnetTAO and SubnetLocked into subnet accounts to make TotalIssuance match in balances and subtensor + .saturating_add(migrations::migrate_subnet_balances::migrate_subnet_balances::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_rao.rs b/pallets/subtensor/src/migrations/migrate_rao.rs index 6092d41c6f..d500cc98c9 100644 --- a/pallets/subtensor/src/migrations/migrate_rao.rs +++ b/pallets/subtensor/src/migrations/migrate_rao.rs @@ -91,7 +91,8 @@ pub fn migrate_rao() -> Weight { // .checked_div(I96F32::from_num(1_000_000_000)) // .unwrap_or(I96F32::from_num(0.0)), // ); - Pallet::::add_balance_to_coldkey_account(&owner, remaining_lock.into()); + let credit = Pallet::::mint_tao(remaining_lock.into()); + let _ = Pallet::::spend_tao(&owner, credit, remaining_lock.into()); SubnetLocked::::insert(netuid, TaoBalance::ZERO); // Clear lock amount. SubnetTAO::::insert(netuid, pool_initial_tao); TotalStake::::mutate(|total| { @@ -108,7 +109,7 @@ pub fn migrate_rao() -> Weight { // Set Owner as the coldkey. SubnetOwnerHotkey::::insert(netuid, owner_coldkey.clone()); // Associate the coldkey to coldkey. - Pallet::::create_account_if_non_existent(&owner_coldkey, &owner_coldkey); + let _ = Pallet::::create_account_if_non_existent(&owner_coldkey, &owner_coldkey); // Only register the owner coldkey if it's not already a hotkey on the subnet. if !Uids::::contains_key(*netuid, &owner_coldkey) { diff --git a/pallets/subtensor/src/migrations/migrate_subnet_balances.rs b/pallets/subtensor/src/migrations/migrate_subnet_balances.rs new file mode 100644 index 0000000000..06bcdc59f4 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_subnet_balances.rs @@ -0,0 +1,90 @@ +use super::*; +use frame_support::{ + traits::{Get, fungible::Inspect}, + weights::Weight, +}; + +/// Performs migration to mint SubnetTAO and subnet locked funds into subnet accounts. +/// +/// # Arguments +/// +/// # Returns +/// +/// * `Weight` - The computational weight of this operation. +/// +pub fn migrate_subnet_balances() -> Weight { + let migration_name = b"migrate_subnet_balances".to_vec(); + let mut weight = T::DbWeight::get().reads(1); + + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + //////////////////////////////////////////////////////// + // Actual migration + + // Mint SubnetTAO into subnet accounts + let mut total_subnet_tao = TaoBalance::ZERO; + SubnetTAO::::iter().for_each(|(netuid, tao)| { + if let Some(subnet_account) = Pallet::::get_subnet_account_id(netuid) { + let credit = Pallet::::mint_tao(tao); + let _ = Pallet::::spend_tao(&subnet_account, credit, tao); + total_subnet_tao = total_subnet_tao.saturating_add(tao); + weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 2)); + } + }); + + // Mint SubnetLocked into subnet accounts + let mut total_subnet_locked = TaoBalance::ZERO; + SubnetLocked::::iter().for_each(|(netuid, tao)| { + if let Some(subnet_account) = Pallet::::get_subnet_account_id(netuid) { + let credit = Pallet::::mint_tao(tao); + let _ = Pallet::::spend_tao(&subnet_account, credit, tao); + total_subnet_locked = total_subnet_locked.saturating_add(tao); + weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 2)); + } + }); + + // mint_tao increases subtensor TotalIssuance, but this is not the intention here because + // SubnetTAO and SubnetLocked are already accounted in it. Reduce it back. + TotalIssuance::::mutate(|total| { + *total = total.saturating_sub(total_subnet_tao.saturating_add(total_subnet_locked)); + }); + + // Update the total issuance in storage + let balances_total_issuance = ::Currency::total_issuance(); + let subtensor_total_issuance = TotalIssuance::::get(); + weight = weight.saturating_add(T::DbWeight::get().reads(2)); + if balances_total_issuance != subtensor_total_issuance { + log::warn!( + "Balances and Subtensor total issuance still do not match: {} vs {}. Making them match now.", + balances_total_issuance, + subtensor_total_issuance + ); + log::warn!(" total_subnet_locked = {}", total_subnet_locked); + log::warn!(" balances_total_issuance = {}", balances_total_issuance); + TotalIssuance::::put(balances_total_issuance); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + + //////////////////////////////////////////////////////// + + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + target: "runtime", + "Migration '{}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + weight +} diff --git a/pallets/subtensor/src/migrations/migrate_subnet_tao_to_subnet_balance.rs b/pallets/subtensor/src/migrations/migrate_subnet_tao_to_subnet_balance.rs new file mode 100644 index 0000000000..8d7d465aa3 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_subnet_tao_to_subnet_balance.rs @@ -0,0 +1,4 @@ + // /// --- MAP ( netuid ) --> tao_in_subnet | Returns the amount of TAO in the subnet. + // #[pallet::storage] + // pub type SubnetTAO = + // StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultZeroTao>; \ No newline at end of file diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 07d72c8d7c..4aac757acd 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -55,6 +55,7 @@ pub mod migrate_set_nominator_min_stake; pub mod migrate_set_registration_enable; pub mod migrate_set_subtoken_enabled; pub mod migrate_stake_threshold; +pub mod migrate_subnet_balances; pub mod migrate_subnet_limit_to_default; pub mod migrate_subnet_locked; pub mod migrate_subnet_symbols; diff --git a/pallets/subtensor/src/staking/account.rs b/pallets/subtensor/src/staking/account.rs index 20a6ff3036..3252c0836f 100644 --- a/pallets/subtensor/src/staking/account.rs +++ b/pallets/subtensor/src/staking/account.rs @@ -6,7 +6,7 @@ impl Pallet { hotkey: &T::AccountId, ) -> DispatchResult { // Ensure the hotkey is not already associated with a coldkey - Self::create_account_if_non_existent(coldkey, hotkey); + Self::create_account_if_non_existent(coldkey, hotkey)?; Ok(()) } diff --git a/pallets/subtensor/src/staking/add_stake.rs b/pallets/subtensor/src/staking/add_stake.rs index a4ad9b92cf..b88e75cd31 100644 --- a/pallets/subtensor/src/staking/add_stake.rs +++ b/pallets/subtensor/src/staking/add_stake.rs @@ -1,4 +1,3 @@ -use substrate_fixed::types::I96F32; use subtensor_runtime_common::{NetUid, TaoBalance}; use subtensor_swap_interface::{Order, SwapHandler}; @@ -49,8 +48,6 @@ impl Pallet { "do_add_stake( origin:{coldkey:?} hotkey:{hotkey:?}, netuid:{netuid:?}, stake_to_be_added:{stake_to_be_added:?} )" ); - Self::ensure_subtoken_enabled(netuid)?; - // 2. Validate user input Self::validate_add_stake( &coldkey, @@ -61,19 +58,13 @@ impl Pallet { false, )?; - // 3. Ensure the remove operation from the coldkey is a success. - let tao_staked: I96F32 = - Self::remove_balance_from_coldkey_account(&coldkey, stake_to_be_added.into())? - .to_u64() - .into(); - - // 4. Swap the stake into alpha on the subnet and increase counters. + // 3. Swap the stake into alpha on the subnet and increase counters. // Emit the staking event. Self::stake_into_subnet( &hotkey, &coldkey, netuid, - tao_staked.saturating_to_num::().into(), + stake_to_be_added, T::SwapInterface::max_price(), true, false, @@ -156,17 +147,13 @@ impl Pallet { Self::maybe_become_delegate(&hotkey); } - // 5. Ensure the remove operation from the coldkey is a success. - let tao_staked = - Self::remove_balance_from_coldkey_account(&coldkey, possible_stake.into())?; - - // 6. Swap the stake into alpha on the subnet and increase counters. + // 5. Swap the stake into alpha on the subnet and increase counters. // Emit the staking event. Self::stake_into_subnet( &hotkey, &coldkey, netuid, - tao_staked, + possible_stake, limit_price, true, false, diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 5c785f199b..38b495e872 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -1,11 +1,4 @@ use alloc::collections::BTreeMap; -use frame_support::traits::{ - Imbalance, - tokens::{ - Fortitude, Precision, Preservation, - fungible::{Balanced as _, Inspect as _}, - }, -}; use safe_math::*; use share_pool::SafeFloat; use substrate_fixed::types::U96F32; @@ -132,7 +125,16 @@ impl Pallet { // Creates a cold - hot pairing account if the hotkey is not already an active account. // - pub fn create_account_if_non_existent(coldkey: &T::AccountId, hotkey: &T::AccountId) { + pub fn create_account_if_non_existent( + coldkey: &T::AccountId, + hotkey: &T::AccountId, + ) -> DispatchResult { + // Only allow to register non-system hotkeys + ensure!( + Self::is_subnet_account_id(hotkey).is_none(), + Error::::NonAssociatedColdKey + ); + if !Self::hotkey_account_exists(hotkey) { Owner::::insert(hotkey, coldkey); @@ -150,6 +152,17 @@ impl Pallet { StakingHotkeys::::insert(coldkey, staking_hotkeys); } } + Ok(()) + } + + pub fn set_hotkey_owner(coldkey: &T::AccountId, hotkey: &T::AccountId) -> DispatchResult { + // Only allow to register non-system hotkeys + ensure!( + Self::is_subnet_account_id(hotkey).is_none(), + Error::::NonAssociatedColdKey + ); + Owner::::insert(hotkey, coldkey); + Ok(()) } //// If the hotkey is not a delegate, make it a delegate. @@ -233,19 +246,18 @@ impl Pallet { // Remove the stake from the nominator account. (this is a more forceful unstake operation which ) // Actually deletes the staking account. // Do not apply any fees - let maybe_cleared_stake = Self::unstake_from_subnet( + if Self::unstake_from_subnet( hotkey, coldkey, + coldkey, netuid, alpha_stake, T::SwapInterface::min_price(), false, - ); - - if let Ok(cleared_stake) = maybe_cleared_stake { - // Add the stake to the coldkey account. - Self::add_balance_to_coldkey_account(coldkey, cleared_stake.into()); - } else { + ) + .is_err() + { + // Ignore errors if unstaking fails // Just clear small alpha let alpha = Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); @@ -268,92 +280,6 @@ impl Pallet { } } - pub fn add_balance_to_coldkey_account( - coldkey: &T::AccountId, - amount: <::Currency as fungible::Inspect<::AccountId>>::Balance, - ) { - // infallible - let _ = ::Currency::deposit(coldkey, amount, Precision::BestEffort); - } - - pub fn can_remove_balance_from_coldkey_account( - coldkey: &T::AccountId, - amount: <::Currency as fungible::Inspect<::AccountId>>::Balance, - ) -> bool { - let current_balance = Self::get_coldkey_balance(coldkey); - if amount > current_balance { - return false; - } - - // This bit is currently untested. @todo - - ::Currency::can_withdraw(coldkey, amount) - .into_result(false) - .is_ok() - } - - pub fn get_coldkey_balance( - coldkey: &T::AccountId, - ) -> <::Currency as fungible::Inspect<::AccountId>>::Balance - { - ::Currency::reducible_balance( - coldkey, - Preservation::Expendable, - Fortitude::Polite, - ) - } - - #[must_use = "Balance must be used to preserve total issuance of token"] - pub fn remove_balance_from_coldkey_account( - coldkey: &T::AccountId, - amount: <::Currency as fungible::Inspect<::AccountId>>::Balance, - ) -> Result { - if amount.is_zero() { - return Ok(TaoBalance::ZERO); - } - - let credit = ::Currency::withdraw( - coldkey, - amount, - Precision::BestEffort, - Preservation::Preserve, - Fortitude::Polite, - ) - .map_err(|_| Error::::BalanceWithdrawalError)? - .peek(); - - if credit.is_zero() { - return Err(Error::::ZeroBalanceAfterWithdrawn.into()); - } - - Ok(credit.into()) - } - - pub fn kill_coldkey_account( - coldkey: &T::AccountId, - amount: <::Currency as fungible::Inspect<::AccountId>>::Balance, - ) -> Result { - if amount.is_zero() { - return Ok(0.into()); - } - - let credit = ::Currency::withdraw( - coldkey, - amount, - Precision::Exact, - Preservation::Expendable, - Fortitude::Force, - ) - .map_err(|_| Error::::BalanceWithdrawalError)? - .peek(); - - if credit.is_zero() { - return Err(Error::::ZeroBalanceAfterWithdrawn.into()); - } - - Ok(credit) - } - pub fn is_user_liquidity_enabled(netuid: NetUid) -> bool { T::SwapInterface::is_user_liquidity_enabled(netuid) } diff --git a/pallets/subtensor/src/staking/move_stake.rs b/pallets/subtensor/src/staking/move_stake.rs index 8e94339339..aafefa28ed 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -358,12 +358,18 @@ impl Pallet { let tao_unstaked = Self::unstake_from_subnet( origin_hotkey, origin_coldkey, + origin_coldkey, origin_netuid, move_amount, T::SwapInterface::min_price(), drop_fee_origin, )?; + // Transfer unstaked TAO from origin_coldkey to destination_coldkey + if origin_coldkey != destination_coldkey { + Self::transfer_tao(origin_coldkey, destination_coldkey, tao_unstaked)?; + } + // Stake the unstaked amount into the destination. // Because of the fee, the tao_unstaked may be too low if initial stake is low. In that case, // do not restake. @@ -471,9 +477,9 @@ impl Pallet { } // Corner case: SubnetTAO for any of two subnets is zero - let subnet_tao_1 = SubnetTAO::::get(origin_netuid) + let subnet_tao_1 = Self::get_subnet_tao(origin_netuid) .saturating_add(SubnetTaoProvided::::get(origin_netuid)); - let subnet_tao_2 = SubnetTAO::::get(destination_netuid) + let subnet_tao_2 = Self::get_subnet_tao(destination_netuid) .saturating_add(SubnetTaoProvided::::get(destination_netuid)); if subnet_tao_1.is_zero() || subnet_tao_2.is_zero() { return Err(Error::::ZeroMaxStakeAmount.into()); diff --git a/pallets/subtensor/src/staking/remove_stake.rs b/pallets/subtensor/src/staking/remove_stake.rs index 0750456106..074b520dd2 100644 --- a/pallets/subtensor/src/staking/remove_stake.rs +++ b/pallets/subtensor/src/staking/remove_stake.rs @@ -67,18 +67,16 @@ impl Pallet { )?; // 3. Swap the alpba to tao and update counters for this subnet. - let tao_unstaked = Self::unstake_from_subnet( + Self::unstake_from_subnet( &hotkey, &coldkey, + &coldkey, netuid, alpha_unstaked, T::SwapInterface::min_price(), false, )?; - // 4. We add the balance to the coldkey. If the above fails we will not credit this coldkey. - Self::add_balance_to_coldkey_account(&coldkey, tao_unstaked.into()); - // 5. If the stake is below the minimum, we clear the nomination from storage. Self::clear_small_nomination_if_required(&hotkey, &coldkey, netuid); @@ -159,18 +157,16 @@ impl Pallet { if !alpha_unstaked.is_zero() { // Swap the alpha to tao and update counters for this subnet. - let tao_unstaked = Self::unstake_from_subnet( + Self::unstake_from_subnet( &hotkey, &coldkey, + &coldkey, netuid, alpha_unstaked, T::SwapInterface::min_price(), false, )?; - // Add the balance to the coldkey. If the above fails we will not credit this coldkey. - Self::add_balance_to_coldkey_account(&coldkey, tao_unstaked.into()); - // If the stake is below the minimum, we clear the nomination from storage. Self::clear_small_nomination_if_required(&hotkey, &coldkey, netuid); } @@ -255,6 +251,7 @@ impl Pallet { let tao_unstaked = Self::unstake_from_subnet( &hotkey, &coldkey, + &coldkey, netuid, alpha_unstaked, T::SwapInterface::min_price(), @@ -358,22 +355,20 @@ impl Pallet { )?; // 4. Swap the alpha to tao and update counters for this subnet. - let tao_unstaked = Self::unstake_from_subnet( + Self::unstake_from_subnet( &hotkey, &coldkey, + &coldkey, netuid, possible_alpha, limit_price, false, )?; - // 5. We add the balance to the coldkey. If the above fails we will not credit this coldkey. - Self::add_balance_to_coldkey_account(&coldkey, tao_unstaked.into()); - - // 6. If the stake is below the minimum, we clear the nomination from storage. + // 5. If the stake is below the minimum, we clear the nomination from storage. Self::clear_small_nomination_if_required(&hotkey, &coldkey, netuid); - // 7. Check if stake lowered below MinStake and remove Pending children if it did + // 6. Check if stake lowered below MinStake and remove Pending children if it did if Self::get_total_stake_for_hotkey(&hotkey) < StakeThreshold::::get().into() { Self::get_all_subnet_netuids().iter().for_each(|netuid| { PendingChildKeys::::remove(netuid, &hotkey); @@ -561,7 +556,7 @@ impl Pallet { // Credit each share directly to coldkey free balance. for p in portions { if p.share > 0 { - Self::add_balance_to_coldkey_account(&p.cold, p.share.into()); + Self::transfer_tao_from_subnet(netuid, &p.cold, p.share.into())?; } } } @@ -596,8 +591,10 @@ impl Pallet { TaoBalance::ZERO }; - if !refund.is_zero() { - Self::add_balance_to_coldkey_account(&owner_coldkey, refund); + if !refund.is_zero() + && let Some(subnet_account) = Self::get_subnet_account_id(netuid) + { + let _ = Self::transfer_tao(&subnet_account, &owner_coldkey, refund); } Ok(()) diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 5e22cc09ac..a0abf7ea84 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -739,9 +739,11 @@ impl Pallet { /// Unstakes alpha from a subnet for a given hotkey and coldkey pair. /// /// We update the pools associated with a subnet as well as update hotkey alpha shares. + /// Credits the unstaked TAO to the benefitiary account pub fn unstake_from_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, + benefitiary: &T::AccountId, netuid: NetUid, alpha: AlphaBalance, price_limit: TaoBalance, @@ -764,6 +766,9 @@ impl Pallet { Self::increase_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, refund); } + // Transfer unstaked TAO from subnet account to the coldkey. + Self::transfer_tao_from_subnet(netuid, benefitiary, swap_result.amount_paid_out.into())?; + // Swap (in a fee-less way) the block builder alpha fee let mut fee_outflow = 0_u64; let maybe_block_author_coldkey = T::AuthorshipProvider::author(); @@ -774,10 +779,11 @@ impl Pallet { T::SwapInterface::min_price::(), true, )?; - Self::add_balance_to_coldkey_account( + Self::transfer_tao_from_subnet( + netuid, &block_author_coldkey, bb_swap_result.amount_paid_out.into(), - ); + )?; fee_outflow = bb_swap_result.amount_paid_out.into(); } else { // block author is not found, burn this alpha @@ -843,8 +849,12 @@ impl Pallet { set_limit: bool, drop_fees: bool, ) -> Result { + // Transfer TAO from coldkey to the subnet account. + // Actual transfered may be different within ED amount. + let tao_staked = Self::transfer_tao_to_subnet(netuid, coldkey, tao)?; + // Swap the tao to alpha. - let swap_result = Self::swap_tao_for_alpha(netuid, tao, price_limit, drop_fees)?; + let swap_result = Self::swap_tao_for_alpha(netuid, tao_staked, price_limit, drop_fees)?; ensure!( !swap_result.amount_paid_out.is_zero(), @@ -878,10 +888,15 @@ impl Pallet { // Increase the balance of the block author let maybe_block_author_coldkey = T::AuthorshipProvider::author(); if let Some(block_author_coldkey) = maybe_block_author_coldkey { - Self::add_balance_to_coldkey_account( + // TAO was transferred to subnet account in the beginning of this fn + // swap_tao_for_alpha guarantees that input amount of TAO was split into + // reserve delta + fee_to_block_author. + // Now transfer the fee from subnet account to block builder. + Self::transfer_tao_from_subnet( + netuid, &block_author_coldkey, swap_result.fee_to_block_author.into(), - ); + )?; } else { // Block author is not found - burn this TAO // Pallet balances total issuance was taken care of when balance was withdrawn for this swap @@ -911,7 +926,7 @@ impl Pallet { Self::deposit_event(Event::StakeAdded( coldkey.clone(), hotkey.clone(), - tao, + tao_staked, swap_result.amount_paid_out.into(), netuid, swap_result.fee_paid.to_u64(), @@ -921,7 +936,7 @@ impl Pallet { "StakeAdded( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee {} )", coldkey.clone(), hotkey.clone(), - tao, + tao_staked, swap_result.amount_paid_out, netuid, swap_result.fee_paid, diff --git a/pallets/subtensor/src/subnets/leasing.rs b/pallets/subtensor/src/subnets/leasing.rs index cc1094d227..d3e1b84df5 100644 --- a/pallets/subtensor/src/subnets/leasing.rs +++ b/pallets/subtensor/src/subnets/leasing.rs @@ -219,7 +219,7 @@ impl Pallet { Error::::BeneficiaryDoesNotOwnHotkey ); SubnetOwner::::insert(lease.netuid, lease.beneficiary.clone()); - Self::set_subnet_owner_hotkey(lease.netuid, &hotkey); + Self::set_subnet_owner_hotkey(lease.netuid, &hotkey)?; // Stop tracking the lease coldkey and hotkey let _ = frame_system::Pallet::::dec_providers(&lease.coldkey).defensive(); diff --git a/pallets/subtensor/src/subnets/registration.rs b/pallets/subtensor/src/subnets/registration.rs index afb09ed0eb..30d3a7d1e1 100644 --- a/pallets/subtensor/src/subnets/registration.rs +++ b/pallets/subtensor/src/subnets/registration.rs @@ -74,7 +74,7 @@ impl Pallet { ); // 6) ensure pairing exists and is correct - Self::create_account_if_non_existent(&coldkey, &hotkey); + let _ = Self::create_account_if_non_existent(&coldkey, &hotkey); ensure!( Self::coldkey_owns_hotkey(&coldkey, &hotkey), Error::::NonAssociatedColdKey @@ -97,7 +97,7 @@ impl Pallet { // 8) burn payment (same mechanics as old burned_register) let actual_burn_amount = - Self::remove_balance_from_coldkey_account(&coldkey, registration_cost.into())?; + Self::transfer_tao_to_subnet(netuid, &coldkey, registration_cost.into())?; let burned_alpha = Self::swap_tao_for_alpha( netuid, @@ -201,7 +201,9 @@ impl Pallet { let balance_to_add: u64 = 1_000_000_000_000; Self::increase_issuance(100_000_000_000_u64.into()); // We are creating tokens here from the coinbase. - Self::add_balance_to_coldkey_account(&coldkey, balance_to_add.into()); + // Mint free TAO + let credit = Self::mint_tao(balance_to_add.into()); + let _ = Self::spend_tao(&coldkey, credit, balance_to_add.into()); // --- 6. Deposit successful event. log::debug!("Faucet( coldkey:{coldkey:?} amount:{balance_to_add:?} ) "); diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index 4eaaf7700e..1727e1ce00 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -1,6 +1,8 @@ use super::*; +use frame_support::PalletId; use safe_math::FixedExt; use sp_core::Get; +use sp_runtime::traits::AccountIdConversion; use substrate_fixed::types::U96F32; use subtensor_runtime_common::{NetUid, TaoBalance}; impl Pallet { @@ -125,6 +127,12 @@ impl Pallet { Error::::NonAssociatedColdKey ); + // Ensure that hotkey is not a special account + ensure!( + Self::is_subnet_account_id(hotkey).is_none(), + Error::::NonAssociatedColdKey + ); + // --- 3. Ensure the mechanism is Dynamic. ensure!(mechid == 1, Error::::MechanismDoesNotExist); @@ -165,21 +173,12 @@ impl Pallet { Error::::CannotAffordLockCost ); - // --- 7. Perform the lock operation. - let actual_tao_lock_amount = - Self::remove_balance_from_coldkey_account(&coldkey, lock_amount.into())?; - log::debug!("actual_tao_lock_amount: {actual_tao_lock_amount:?}"); - - // --- 8. Set the lock amount for use to determine pricing. - Self::set_network_last_lock(actual_tao_lock_amount); - Self::set_network_last_lock_block(current_block); - - // --- 9. If we identified a subnet to prune, do it now. + // --- 7. If we identified a subnet to prune, do it now. if let Some(prune_netuid) = recycle_netuid { Self::do_dissolve_network(prune_netuid)?; } - // --- 10. Determine netuid to register. If we pruned a subnet, reuse that netuid. + // --- 8. Determine netuid to register. If we pruned a subnet, reuse that netuid. let netuid_to_register: NetUid = match recycle_netuid { Some(prune_netuid) => prune_netuid, None => Self::get_next_netuid(), @@ -193,8 +192,17 @@ impl Pallet { Self::init_new_network(netuid_to_register, default_tempo); log::debug!("init_new_network: {netuid_to_register:?}"); - // --- 13. Add the caller to the neuron set. - Self::create_account_if_non_existent(&coldkey, hotkey); + // --- 10. Perform the lock operation (transfer TAO from owner's coldkey to subnet account). + let actual_tao_lock_amount = + Self::transfer_tao_to_subnet(netuid_to_register, &coldkey, lock_amount.into())?; + log::debug!("actual_tao_lock_amount: {actual_tao_lock_amount:?}"); + + // --- 11. Set the lock amount for use to determine pricing. + Self::set_network_last_lock(actual_tao_lock_amount); + Self::set_network_last_lock_block(current_block); + + // --- 12. Add the caller to the neuron set. + Self::create_account_if_non_existent(&coldkey, hotkey)?; Self::append_neuron(netuid_to_register, hotkey, current_block); log::debug!("Appended neuron for netuid {netuid_to_register:?}, hotkey: {hotkey:?}"); @@ -227,7 +235,7 @@ impl Pallet { SubnetTAO::::insert(netuid_to_register, pool_initial_tao); SubnetAlphaIn::::insert(netuid_to_register, pool_initial_alpha); SubnetOwner::::insert(netuid_to_register, coldkey.clone()); - SubnetOwnerHotkey::::insert(netuid_to_register, hotkey.clone()); + Self::set_subnet_owner_hotkey(netuid_to_register, hotkey)?; SubnetLocked::::insert(netuid_to_register, actual_tao_lock_amount); SubnetTaoProvided::::insert(netuid_to_register, TaoBalance::ZERO); SubnetAlphaInProvided::::insert(netuid_to_register, AlphaBalance::ZERO); @@ -248,7 +256,10 @@ impl Pallet { } if actual_tao_lock_amount_less_pool_tao > TaoBalance::ZERO { - Self::recycle_tao(actual_tao_lock_amount_less_pool_tao); + // TAO paid for registration is already on the subnet account. Recycle from it if needed. + let subnet_account = Self::get_subnet_account_id(netuid_to_register) + .ok_or(Error::::SubnetNotExists)?; + Self::recycle_tao(&subnet_account, actual_tao_lock_amount_less_pool_tao)?; } if actual_tao_lock_amount > TaoBalance::ZERO && pool_initial_tao > TaoBalance::ZERO { @@ -441,7 +452,7 @@ impl Pallet { ); // Insert/update the hotkey - SubnetOwnerHotkey::::insert(netuid, hotkey); + Self::set_subnet_owner_hotkey(netuid, hotkey)?; // Return success. Ok(()) @@ -450,4 +461,21 @@ impl Pallet { pub fn is_valid_subnet_for_emission(netuid: NetUid) -> bool { FirstEmissionBlockNumber::::get(netuid).is_some() } + + pub fn get_subnet_account_id(netuid: NetUid) -> Option { + if NetworksAdded::::contains_key(netuid) || netuid == NetUid::ROOT { + Some(T::SubtensorPalletId::get().into_sub_account_truncating(u16::from(netuid))) + } else { + None + } + } + + pub fn is_subnet_account_id(account: &T::AccountId) -> Option { + let pallet_id = T::SubtensorPalletId::get(); + + match PalletId::try_from_sub_account::(account) { + Some((decoded_pallet_id, netuid)) if decoded_pallet_id == pallet_id => Some(netuid), + _ => None, + } + } } diff --git a/pallets/subtensor/src/swap/swap_coldkey.rs b/pallets/subtensor/src/swap/swap_coldkey.rs index 68cf6d8b56..5ca4a4105d 100644 --- a/pallets/subtensor/src/swap/swap_coldkey.rs +++ b/pallets/subtensor/src/swap/swap_coldkey.rs @@ -29,14 +29,10 @@ impl Pallet { Self::transfer_coldkey_stake(netuid, old_coldkey, new_coldkey); } Self::transfer_staking_hotkeys(old_coldkey, new_coldkey); - Self::transfer_hotkeys_ownership(old_coldkey, new_coldkey); + Self::transfer_hotkeys_ownership(old_coldkey, new_coldkey)?; // Transfer any remaining balance from old_coldkey to new_coldkey - let remaining_balance = Self::get_coldkey_balance(old_coldkey); - if remaining_balance > 0.into() { - Self::kill_coldkey_account(old_coldkey, remaining_balance)?; - Self::add_balance_to_coldkey_account(new_coldkey, remaining_balance); - } + Self::transfer_all_tao_and_kill(old_coldkey, new_coldkey)?; Self::set_last_tx_block(new_coldkey, Self::get_current_block_as_u64()); @@ -49,15 +45,8 @@ impl Pallet { /// Charges the swap cost from the coldkey's account and recycles the tokens. pub fn charge_swap_cost(coldkey: &T::AccountId, swap_cost: TaoBalance) -> DispatchResult { - let burn_amount = Self::remove_balance_from_coldkey_account(coldkey, swap_cost.into()) + Self::recycle_tao(coldkey, swap_cost) .map_err(|_| Error::::NotEnoughBalanceToPaySwapColdKey)?; - - if burn_amount < swap_cost { - return Err(Error::::NotEnoughBalanceToPaySwapColdKey.into()); - } - - Self::recycle_tao(burn_amount); - Ok(()) } @@ -148,14 +137,17 @@ impl Pallet { } /// Transfer the ownership of the hotkeys owned by the old coldkey to the new coldkey. - fn transfer_hotkeys_ownership(old_coldkey: &T::AccountId, new_coldkey: &T::AccountId) { + fn transfer_hotkeys_ownership( + old_coldkey: &T::AccountId, + new_coldkey: &T::AccountId, + ) -> DispatchResult { let old_owned_hotkeys: Vec = OwnedHotkeys::::get(old_coldkey); let mut new_owned_hotkeys: Vec = OwnedHotkeys::::get(new_coldkey); for owned_hotkey in old_owned_hotkeys.iter() { // Remove the hotkey from the old coldkey. Owner::::remove(owned_hotkey); // Add the hotkey to the new coldkey. - Owner::::insert(owned_hotkey, new_coldkey.clone()); + Self::set_hotkey_owner(new_coldkey, owned_hotkey)?; // Addd the owned hotkey to the new set of owned hotkeys. if !new_owned_hotkeys.contains(owned_hotkey) { new_owned_hotkeys.push(owned_hotkey.clone()); @@ -163,5 +155,6 @@ impl Pallet { } OwnedHotkeys::::remove(old_coldkey); OwnedHotkeys::::insert(new_coldkey, new_owned_hotkeys); + Ok(()) } } diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index a7da13058a..74a8690cb6 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -113,12 +113,8 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(3, 0)); - // 14. Remove the swap cost from the coldkey's account - let actual_recycle_amount = - Self::remove_balance_from_coldkey_account(&coldkey, swap_cost.into())?; - - // 18. Recycle the tokens - Self::recycle_tao(actual_recycle_amount); + // 14. Remove the swap cost from the coldkey's account + Recycle the tokens + Self::recycle_tao(&coldkey, swap_cost.into())?; weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); // 19. Perform the hotkey swap @@ -193,7 +189,7 @@ impl Pallet { // 2. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. Owner::::remove(old_hotkey); - Owner::::insert(new_hotkey, coldkey.clone()); + Self::set_hotkey_owner(coldkey, new_hotkey)?; weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); // 3. Swap OwnedHotkeys. @@ -305,18 +301,14 @@ impl Pallet { Error::::NotEnoughBalanceToPaySwapHotKey ); - // 5. Remove the swap cost from the coldkey's account - let actual_recycle_amount = Self::remove_balance_from_coldkey_account(coldkey, swap_cost)?; - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 0)); - - // 6. Recycle the tokens - Self::recycle_tao(actual_recycle_amount); + // 5. Remove the swap cost from the coldkey's account + Recycle the tokens + Self::recycle_tao(coldkey, swap_cost)?; weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); // 7. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. // Owner::::remove(old_hotkey); - Owner::::insert(new_hotkey, coldkey.clone()); + Self::create_account_if_non_existent(coldkey, new_hotkey)?; weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); // 8. Swap OwnedHotkeys. @@ -484,7 +476,7 @@ impl Pallet { if let Ok(old_subnet_owner_hotkey) = SubnetOwnerHotkey::::try_get(netuid) { weight.saturating_accrue(T::DbWeight::get().reads(1)); if old_subnet_owner_hotkey == *old_hotkey { - SubnetOwnerHotkey::::insert(netuid, new_hotkey); + Self::set_subnet_owner_hotkey(netuid, new_hotkey)?; weight.saturating_accrue(T::DbWeight::get().writes(1)); } } diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index ef721b671b..4f599c14c8 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -341,7 +341,7 @@ fn test_add_singular_child() { ), Err(Error::::NonAssociatedColdKey.into()) ); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); step_rate_limit(&TransactionType::SetChildren, netuid); assert_eq!( SubtensorModule::do_schedule_children( @@ -2233,7 +2233,7 @@ fn test_do_remove_stake_clears_pending_childkeys() { // Add network and register hotkey add_network(netuid, 13, 0); register_ok_neuron(netuid, hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 10_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 10_000_000_000_000_u64.into()); SubtokenEnabled::::insert(netuid, true); let reserve = 1_000_000_000_000_000_u64; @@ -2644,12 +2644,9 @@ fn test_childkey_set_weights_single_parent() { let stake_to_give_child = AlphaBalance::from(109_999); // Register parent with minimal stake and child with high stake - SubtensorModule::add_balance_to_coldkey_account(&coldkey_parent, 1.into()); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_child, - balance_to_give_child + 10.into(), - ); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_weight_setter, 1_000_000.into()); + add_balance_to_coldkey_account(&coldkey_parent, 1.into()); + add_balance_to_coldkey_account(&coldkey_child, balance_to_give_child + 10.into()); + add_balance_to_coldkey_account(&coldkey_weight_setter, 1_000_000.into()); // Add neurons for parent, child and weight_setter register_ok_neuron(netuid, parent, coldkey_parent, 1); @@ -2752,10 +2749,7 @@ fn test_set_weights_no_parent() { let balance_to_give_child = TaoBalance::from(109_999); let stake_to_give_child = AlphaBalance::from(109_999); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey, - balance_to_give_child + 10.into(), - ); + add_balance_to_coldkey_account(&coldkey, balance_to_give_child + 10.into()); // Is registered register_ok_neuron(netuid, hotkey, coldkey, 1); @@ -2864,11 +2858,11 @@ fn test_childkey_take_drain() { register_ok_neuron(netuid, child_hotkey, child_coldkey, 0); register_ok_neuron(netuid, parent_hotkey, parent_coldkey, 1); register_ok_neuron(netuid, miner_hotkey, miner_coldkey, 1); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &parent_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &nominator, TaoBalance::from(stake) + ExistentialDeposit::get(), ); @@ -3004,9 +2998,9 @@ fn test_parent_child_chain_emission() { register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_b, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_c, 1_000.into()); // Swap to alpha let stake_a = 300_000_000_000_u64; @@ -3212,9 +3206,9 @@ fn test_parent_child_chain_epoch() { register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_b, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_c, 1_000.into()); mock::setup_reserves( netuid, @@ -3366,9 +3360,9 @@ fn test_dividend_distribution_with_children() { register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_b, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_c, 1_000.into()); // Swap to alpha let total_tao = I96F32::from_num(300_000 + 100_000 + 50_000); @@ -3600,9 +3594,9 @@ fn test_dynamic_parent_child_relationships() { log::info!("child take 2: {chk_take_2:?}"); // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_parent, (500_000 + 1_000).into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_child1, (50_000 + 1_000).into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_child2, (30_000 + 1_000).into()); + add_balance_to_coldkey_account(&coldkey_parent, (500_000 + 1_000).into()); + add_balance_to_coldkey_account(&coldkey_child1, (50_000 + 1_000).into()); + add_balance_to_coldkey_account(&coldkey_child2, (30_000 + 1_000).into()); let reserve = 1_000_000_000_000_u64; mock::setup_reserves(netuid, reserve.into(), reserve.into()); @@ -3898,8 +3892,8 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { register_ok_neuron(netuid, hotkey_b, coldkey_a, 0); // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); + add_balance_to_coldkey_account(&coldkey_a, 1_000.into()); // Swap to alpha let total_tao = 300_000 + 100_000; @@ -4451,7 +4445,7 @@ fn test_register_network_schedules_root_validators() { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(&subnet_owner_coldkey, lock_cost.into()); + add_balance_to_coldkey_account(&subnet_owner_coldkey, lock_cost.into()); TotalIssuance::::mutate(|total| { *total = total.saturating_add(lock_cost); }); diff --git a/pallets/subtensor/src/tests/claim_root.rs b/pallets/subtensor/src/tests/claim_root.rs index f86ca0b1e6..c0a3e4dbdf 100644 --- a/pallets/subtensor/src/tests/claim_root.rs +++ b/pallets/subtensor/src/tests/claim_root.rs @@ -1,10 +1,7 @@ #![allow(clippy::expect_used)] use crate::RootAlphaDividendsPerSubnet; -use crate::tests::mock::{ - RuntimeOrigin, SubtensorModule, Test, add_dynamic_network, new_test_ext, - remove_owner_registration_stake, run_to_block, -}; +use crate::tests::mock::*; use crate::{ DefaultMinRootClaimAmount, Error, MAX_NUM_ROOT_CLAIMS, MAX_ROOT_CLAIM_THRESHOLD, NetworksAdded, NumRootClaim, NumStakingColdkeys, PendingRootAlphaDivs, RootClaimable, RootClaimableThreshold, @@ -50,7 +47,7 @@ fn test_claim_root_with_drain_emissions() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -58,7 +55,7 @@ fn test_claim_root_with_drain_emissions() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -203,13 +200,13 @@ fn test_claim_root_adding_stake_proportionally_for_two_stakers() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 1_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &alice_coldkey, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &bob_coldkey, NetUid::ROOT, @@ -217,7 +214,7 @@ fn test_claim_root_adding_stake_proportionally_for_two_stakers() { ); let root_stake_rate = 0.1f64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &other_coldkey, NetUid::ROOT, @@ -225,7 +222,7 @@ fn test_claim_root_adding_stake_proportionally_for_two_stakers() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -306,20 +303,20 @@ fn test_claim_root_adding_stake_disproportionally_for_two_stakers() { let other_root_stake = 7_000_000u64; let alice_root_stake_rate = 0.1f64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &alice_coldkey, NetUid::ROOT, alice_root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &bob_coldkey, NetUid::ROOT, bob_root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &other_coldkey, NetUid::ROOT, @@ -327,7 +324,7 @@ fn test_claim_root_adding_stake_disproportionally_for_two_stakers() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -405,13 +402,13 @@ fn test_claim_root_with_changed_stake() { NetworksAdded::::insert(NetUid::ROOT, true); let root_stake = 8_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &alice_coldkey, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &bob_coldkey, NetUid::ROOT, @@ -419,7 +416,7 @@ fn test_claim_root_with_changed_stake() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -612,14 +609,14 @@ fn test_claim_root_with_drain_emissions_and_swap_claim_type() { assert_eq!(current_price, 0.5f64); let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, root_stake.into(), ); let root_stake_rate = 0.1f64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &other_coldkey, NetUid::ROOT, @@ -627,7 +624,7 @@ fn test_claim_root_with_drain_emissions_and_swap_claim_type() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -775,7 +772,7 @@ fn test_claim_root_with_run_coinbase() { let root_stake = 200_000_000u64; SubnetTAO::::insert(NetUid::ROOT, TaoBalance::from(root_stake)); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -783,7 +780,7 @@ fn test_claim_root_with_run_coinbase() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -894,7 +891,7 @@ fn test_claim_root_with_block_emissions() { let root_stake = 200_000_000u64; SubnetTAO::::insert(NetUid::ROOT, TaoBalance::from(root_stake)); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -915,7 +912,7 @@ fn test_claim_root_with_block_emissions() { assert!(root_sell_flag, "Root sell flag should be true"); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -959,19 +956,19 @@ fn test_populate_staking_maps() { let netuid2 = NetUid::from(2); let root_stake = 200_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey1, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey2, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey3, netuid2, @@ -1010,7 +1007,7 @@ fn test_claim_root_coinbase_distribution() { let initial_tao = 200_000_000u64; SubnetTAO::::insert(NetUid::ROOT, TaoBalance::from(initial_tao)); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -1018,7 +1015,7 @@ fn test_claim_root_coinbase_distribution() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1127,7 +1124,7 @@ fn test_claim_root_with_swap_coldkey() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -1135,7 +1132,7 @@ fn test_claim_root_with_swap_coldkey() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1214,7 +1211,7 @@ fn test_claim_root_with_swap_hotkey() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -1222,7 +1219,7 @@ fn test_claim_root_with_swap_hotkey() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1330,13 +1327,13 @@ fn test_claim_root_on_network_deregistration() { assert_eq!(current_price, 0.5f64); let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &other_coldkey, NetUid::ROOT, @@ -1344,7 +1341,7 @@ fn test_claim_root_on_network_deregistration() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1471,7 +1468,7 @@ fn test_claim_root_with_unrelated_subnets() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -1479,7 +1476,7 @@ fn test_claim_root_with_unrelated_subnets() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1575,13 +1572,13 @@ fn test_claim_root_fill_root_alpha_dividends_per_subnet() { SubnetAlphaIn::::insert(netuid, alpha_in); let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &other_coldkey, NetUid::ROOT, @@ -1589,7 +1586,7 @@ fn test_claim_root_fill_root_alpha_dividends_per_subnet() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1650,7 +1647,7 @@ fn test_claim_root_with_keep_subnets() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, @@ -1658,7 +1655,7 @@ fn test_claim_root_with_keep_subnets() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1746,14 +1743,14 @@ fn test_claim_root_keep_subnets_swap_claim_type() { assert_eq!(current_price, 0.5f64); let root_stake = 2_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, root_stake.into(), ); let root_stake_rate = 0.1f64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &other_coldkey, NetUid::ROOT, @@ -1761,7 +1758,7 @@ fn test_claim_root_keep_subnets_swap_claim_type() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, @@ -1843,13 +1840,13 @@ fn test_claim_root_with_moved_stake() { NetworksAdded::::insert(NetUid::ROOT, true); let root_stake = 8_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &alice_coldkey, NetUid::ROOT, root_stake.into(), ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &bob_coldkey, NetUid::ROOT, @@ -1857,7 +1854,7 @@ fn test_claim_root_with_moved_stake() { ); let initial_total_hotkey_alpha = 10_000_000u64; - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &owner_coldkey, netuid, diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 8667ef9be0..0d698c1511 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -2987,15 +2987,15 @@ fn test_mining_emission_distribution_with_no_root_sell() { register_ok_neuron(netuid, validator_hotkey, validator_coldkey, 0); register_ok_neuron(netuid, validator_miner_hotkey, validator_miner_coldkey, 1); register_ok_neuron(netuid, miner_hotkey, miner_coldkey, 2); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &validator_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &validator_miner_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &miner_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); @@ -3037,7 +3037,7 @@ fn test_mining_emission_distribution_with_no_root_sell() { step_block(subnet_tempo); // Add stake to validator so it has root stake - SubtensorModule::add_balance_to_coldkey_account(&validator_coldkey, root_stake.into()); + add_balance_to_coldkey_account(&validator_coldkey, root_stake.into()); // init root assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(validator_coldkey), @@ -3182,15 +3182,15 @@ fn test_mining_emission_distribution_with_root_sell() { register_ok_neuron(netuid, validator_hotkey, validator_coldkey, 0); register_ok_neuron(netuid, validator_miner_hotkey, validator_miner_coldkey, 1); register_ok_neuron(netuid, miner_hotkey, miner_coldkey, 2); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &validator_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &validator_miner_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &miner_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); @@ -3232,7 +3232,7 @@ fn test_mining_emission_distribution_with_root_sell() { step_block(subnet_tempo); // Add stake to validator so it has root stake - SubtensorModule::add_balance_to_coldkey_account(&validator_coldkey, root_stake.into()); + add_balance_to_coldkey_account(&validator_coldkey, root_stake.into()); // init root assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(validator_coldkey), @@ -3842,7 +3842,7 @@ fn test_pending_emission_start_call_not_done() { Tempo::::insert(netuid, subnet_tempo); register_ok_neuron(netuid, validator_hotkey, validator_coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &validator_coldkey, TaoBalance::from(stake) + ExistentialDeposit::get(), ); @@ -3854,7 +3854,7 @@ fn test_pending_emission_start_call_not_done() { SubtensorModule::set_max_allowed_validators(netuid, 2); // Add stake to validator so it has root stake - SubtensorModule::add_balance_to_coldkey_account(&validator_coldkey, root_stake.into()); + add_balance_to_coldkey_account(&validator_coldkey, root_stake.into()); // init root assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(validator_coldkey), diff --git a/pallets/subtensor/src/tests/consensus.rs b/pallets/subtensor/src/tests/consensus.rs index 4a85f652a8..495633d131 100644 --- a/pallets/subtensor/src/tests/consensus.rs +++ b/pallets/subtensor/src/tests/consensus.rs @@ -185,7 +185,7 @@ fn init_run_epochs( }; // let stake: u64 = 1; // alternative test: all nodes receive stake, should be same outcome, except stake - SubtensorModule::add_balance_to_coldkey_account(&(U256::from(key)), stake.into()); + add_balance_to_coldkey_account(&(U256::from(key)), stake.into()); SubtensorModule::append_neuron(netuid, &(U256::from(key)), 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &U256::from(key), diff --git a/pallets/subtensor/src/tests/delegate_info.rs b/pallets/subtensor/src/tests/delegate_info.rs index 8c04c9d136..d847e3d008 100644 --- a/pallets/subtensor/src/tests/delegate_info.rs +++ b/pallets/subtensor/src/tests/delegate_info.rs @@ -119,10 +119,7 @@ fn test_get_delegated() { let Some(delegate) = delegate else { continue; }; - SubtensorModule::add_balance_to_coldkey_account( - delegatee, - (*amount + 500_000).into(), - ); + add_balance_to_coldkey_account(delegatee, (*amount + 500_000).into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(*delegatee), *delegate, diff --git a/pallets/subtensor/src/tests/epoch.rs b/pallets/subtensor/src/tests/epoch.rs index 5c516f9f30..02236d892d 100644 --- a/pallets/subtensor/src/tests/epoch.rs +++ b/pallets/subtensor/src/tests/epoch.rs @@ -178,7 +178,7 @@ fn init_run_epochs( }; // let stake: u64 = 1; // alternative test: all nodes receive stake, should be same outcome, except stake - SubtensorModule::add_balance_to_coldkey_account(&(U256::from(key)), stake.into()); + add_balance_to_coldkey_account(&(U256::from(key)), stake.into()); SubtensorModule::append_neuron(netuid, &(U256::from(key)), 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &U256::from(key), @@ -563,7 +563,7 @@ fn test_1_graph() { let stake_amount: TaoBalance = 1_000_000_000.into(); add_network_disable_commit_reveal(netuid, u16::MAX - 1, 0); // set higher tempo to avoid built-in epoch, then manual epoch instead SubtensorModule::set_max_allowed_uids(netuid, 1); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey, stake_amount + ExistentialDeposit::get() + SubtensorModule::get_network_min_lock(), ); @@ -1023,7 +1023,7 @@ fn test_bonds() { // === Register [validator1, validator2, validator3, validator4, server1, server2, server3, server4] for key in 0..n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), max_stake + ExistentialDeposit::get() + SubtensorModule::get_network_min_lock() ); @@ -1317,7 +1317,7 @@ fn test_set_alpha_disabled() { // Enable Liquid Alpha and setup SubtensorModule::set_liquid_alpha_enabled(netuid, true); migrations::migrate_create_root_network::migrate_create_root_network::(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000_u64.into()); assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey,)); let fee = ::SwapInterface::approx_fee_amount( netuid.into(), @@ -1369,7 +1369,7 @@ fn test_active_stake() { // === Register [validator1, validator2, server1, server2] for key in 0..n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), stake + ExistentialDeposit::get() + SubtensorModule::get_network_min_lock(), ); @@ -1590,7 +1590,7 @@ fn test_outdated_weights() { // === Register [validator1, validator2, server1, server2] for key in 0..n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), stake + ExistentialDeposit::get() @@ -1683,7 +1683,7 @@ fn test_outdated_weights() { // === Dereg server2 at uid3 (least emission) + register new key over uid3 let new_key: u64 = n as u64; // register a new key while at max capacity, which means the least incentive uid will be deregistered - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(new_key), stake + ExistentialDeposit::get() @@ -1788,7 +1788,7 @@ fn test_zero_weights() { // === Register [validator, server] for key in 0..n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), ExistentialDeposit::get() + (SubtensorModule::get_network_min_lock() * 2.into()), ); @@ -1809,7 +1809,7 @@ fn test_zero_weights() { )); } for validator in 0..(n / 2) as u64 { - SubtensorModule::add_balance_to_coldkey_account(&U256::from(validator), stake.into()); + add_balance_to_coldkey_account(&U256::from(validator), stake.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &U256::from(validator), &U256::from(validator), @@ -1901,7 +1901,7 @@ fn test_zero_weights() { // === Outdate weights by reregistering servers for new_key in n..n + (n / 2) { // register a new key while at max capacity, which means the least emission uid will be deregistered - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(new_key), ExistentialDeposit::get() + (SubtensorModule::get_network_min_lock() * 2.into()), ); @@ -2001,7 +2001,7 @@ fn test_deregistered_miner_bonds() { // === Register [validator1, validator2, server1, server2] let block_number = System::block_number(); for key in 0..n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), stake + ExistentialDeposit::get() @@ -2085,7 +2085,7 @@ fn test_deregistered_miner_bonds() { // === Dereg server2 at uid3 (least emission) + register new key over uid3 let new_key: u64 = n as u64; // register a new key while at max capacity, which means the least incentive uid will be deregistered let block_number = System::block_number(); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(new_key), stake + ExistentialDeposit::get() @@ -2205,7 +2205,7 @@ fn test_validator_permits() { // === Register [validator1, validator2, server1, server2] for key in 0..network_n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), stake[key as usize] + ExistentialDeposit::get() @@ -2258,7 +2258,7 @@ fn test_validator_permits() { // === Increase server stake above validators for server in &servers { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &(U256::from(*server as u64)), (2 * network_n as u64).into(), ); @@ -2310,7 +2310,7 @@ fn test_get_set_alpha() { // Enable Liquid Alpha and setup SubtensorModule::set_liquid_alpha_enabled(netuid, true); migrations::migrate_create_root_network::migrate_create_root_network::(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000_u64.into()); assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey,)); // Should fail as signer does not own the subnet @@ -2735,7 +2735,7 @@ fn setup_yuma_3_scenario(netuid: NetUid, n: u16, sparse: bool, max_stake: u64, s // === Register for key in 0..n as u64 { - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &U256::from(key), TaoBalance::from(max_stake) + ExistentialDeposit::get() @@ -3875,7 +3875,7 @@ fn test_last_update_size_mismatch() { let stake_amount: u64 = 1_000_000_000; add_network_disable_commit_reveal(netuid, u16::MAX - 1, 0); SubtensorModule::set_max_allowed_uids(netuid, 1); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey, TaoBalance::from(stake_amount) + ExistentialDeposit::get() diff --git a/pallets/subtensor/src/tests/evm.rs b/pallets/subtensor/src/tests/evm.rs index ae0acde27a..d692a72f72 100644 --- a/pallets/subtensor/src/tests/evm.rs +++ b/pallets/subtensor/src/tests/evm.rs @@ -44,7 +44,7 @@ fn test_associate_evm_key_success() { let coldkey = U256::from(1); let hotkey = U256::from(2); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); @@ -93,7 +93,7 @@ fn test_associate_evm_key_different_block_number_success() { let coldkey = U256::from(1); let hotkey = U256::from(2); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); @@ -182,7 +182,7 @@ fn test_associate_evm_key_hotkey_not_registered_in_subnet() { let coldkey = U256::from(1); let hotkey = U256::from(2); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); let pair = ecdsa::Pair::generate().0; let public = pair.public(); @@ -224,7 +224,7 @@ fn test_associate_evm_key_using_wrong_hash_function() { let coldkey = U256::from(1); let hotkey = U256::from(2); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); @@ -268,7 +268,7 @@ fn test_associate_evm_key_rate_limit_exceeded() { let coldkey = U256::from(1); let hotkey = U256::from(2); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); diff --git a/pallets/subtensor/src/tests/leasing.rs b/pallets/subtensor/src/tests/leasing.rs index 0c6ae629c3..01e0c2288f 100644 --- a/pallets/subtensor/src/tests/leasing.rs +++ b/pallets/subtensor/src/tests/leasing.rs @@ -264,7 +264,7 @@ fn test_terminate_lease_works() { // Create a hotkey for the beneficiary let hotkey = U256::from(3); - SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); // Terminate the lease assert_ok!(SubtensorModule::terminate_lease( @@ -356,7 +356,7 @@ fn test_terminate_lease_fails_if_origin_is_not_beneficiary() { // Create a hotkey for the beneficiary let hotkey = U256::from(3); - SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); // Terminate the lease assert_err!( @@ -389,7 +389,7 @@ fn test_terminate_lease_fails_if_lease_has_no_end_block() { // Create a hotkey for the beneficiary let hotkey = U256::from(3); - SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); // Terminate the lease assert_err!( @@ -427,7 +427,7 @@ fn test_terminate_lease_fails_if_lease_has_not_ended() { // Create a hotkey for the beneficiary let hotkey = U256::from(3); - SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&beneficiary, &hotkey); // Terminate the lease assert_err!( @@ -1074,7 +1074,7 @@ fn setup_crowdloan( pallet_crowdloan::Contributions::::insert(id, contributor, amount); } - SubtensorModule::add_balance_to_coldkey_account(&funds_account, cap); + add_balance_to_coldkey_account(&funds_account, cap); // Mark the crowdloan as finalizing pallet_crowdloan::CurrentCrowdloanId::::set(Some(0)); @@ -1099,7 +1099,7 @@ fn setup_leased_network( SubtokenEnabled::::insert(netuid, true); if let Some(tao_to_stake) = tao_to_stake { - SubtensorModule::add_balance_to_coldkey_account(&lease.coldkey, tao_to_stake.into()); + add_balance_to_coldkey_account(&lease.coldkey, tao_to_stake.into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(lease.coldkey), lease.hotkey, diff --git a/pallets/subtensor/src/tests/mechanism.rs b/pallets/subtensor/src/tests/mechanism.rs index 6cf37fbcc1..ef51c7e8d5 100644 --- a/pallets/subtensor/src/tests/mechanism.rs +++ b/pallets/subtensor/src/tests/mechanism.rs @@ -951,7 +951,7 @@ fn test_set_mechanism_weights_happy_path_sets_row_under_subid() { // Make caller a permitted validator with stake SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); - SubtensorModule::add_balance_to_coldkey_account(&ck1, 1.into()); + add_balance_to_coldkey_account(&ck1, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hk1, &ck1, @@ -1008,7 +1008,7 @@ fn test_set_mechanism_weights_above_mechanism_count_fails() { // Make caller a permitted validator with stake SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); - SubtensorModule::add_balance_to_coldkey_account(&ck1, 1.into()); + add_balance_to_coldkey_account(&ck1, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hk1, &ck1, @@ -1066,7 +1066,7 @@ fn test_commit_reveal_mechanism_weights_ok() { SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&ck1, 1.into()); + add_balance_to_coldkey_account(&ck1, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hk1, &ck1, @@ -1150,7 +1150,7 @@ fn test_commit_reveal_above_mechanism_count_fails() { SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&ck1, 1.into()); + add_balance_to_coldkey_account(&ck1, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hk1, &ck1, @@ -1237,8 +1237,8 @@ fn test_reveal_crv3_commits_sub_success() { SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); SubtensorModule::set_validator_permit_for_uid(netuid, uid2, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(3), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(4), 1.into()); + add_balance_to_coldkey_account(&U256::from(3), 1.into()); + add_balance_to_coldkey_account(&U256::from(4), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &U256::from(3), netuid, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &U256::from(4), netuid, 1.into()); @@ -1342,7 +1342,7 @@ fn test_crv3_above_mechanism_count_fails() { let uid2 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey2).expect("uid2"); SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(3), 1.into()); + add_balance_to_coldkey_account(&U256::from(3), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &U256::from(3), netuid, 1.into()); let version_key = SubtensorModule::get_weights_version_key(netuid); @@ -1412,7 +1412,7 @@ fn test_do_commit_crv3_mechanism_weights_committing_too_fast() { // make validator with stake SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, uid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(2), 1.into()); + add_balance_to_coldkey_account(&U256::from(2), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &U256::from(2), @@ -1523,9 +1523,9 @@ fn epoch_mechanism_emergency_mode_distributes_by_stake() { // (leave Weights/Bonds empty for all rows on this sub-subnet) // stake proportions: uid0:uid1:uid2 = 10:30:60 - SubtensorModule::add_balance_to_coldkey_account(&ck0, 10.into()); - SubtensorModule::add_balance_to_coldkey_account(&ck1, 30.into()); - SubtensorModule::add_balance_to_coldkey_account(&ck2, 60.into()); + add_balance_to_coldkey_account(&ck0, 10.into()); + add_balance_to_coldkey_account(&ck1, 30.into()); + add_balance_to_coldkey_account(&ck2, 60.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hk0, &ck0, diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 368851846b..a21581de7f 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -335,7 +335,7 @@ fn test_migrate_commit_reveal_2() { // 2 * stake_amount // ); // // Increase stake for hotkey1 and coldkey1 on netuid_0 -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( +// mock_increase_stake_for_hotkey_and_coldkey_on_subnet( // &hotkey1, // &coldkey1, // netuid_0, @@ -354,7 +354,7 @@ fn test_migrate_commit_reveal_2() { // 3 * stake_amount // ); // // Increase stake for hotkey1 and coldkey1 on netuid_1 -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( +// mock_increase_stake_for_hotkey_and_coldkey_on_subnet( // &hotkey1, // &coldkey1, // netuid_1, @@ -2606,7 +2606,7 @@ fn do_setup_unactive_sn() -> (Vec, Vec) { let coldkey_account_id = U256::from(1111); let hotkey_account_id = U256::from(1111); let burn_cost = SubtensorModule::get_burn(*netuid); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, burn_cost.into()); + add_balance_to_coldkey_account(&coldkey_account_id, burn_cost.into()); TotalIssuance::::mutate(|total_issuance| { let updated_total = u64::from(*total_issuance) .checked_add(u64::from(burn_cost)) @@ -3269,7 +3269,7 @@ fn test_migrate_fix_bad_hk_swap_only_genesis() { ::AccountId::decode(&mut account_id32_slice).expect("Invalid hotkey"); // Give balance to coldkey - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 100_000222.into()); + add_balance_to_coldkey_account(&coldkey_account_id, 100_000222.into()); // Give stake to hotkey let stake_added = 222222.into(); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -3330,7 +3330,7 @@ fn test_migrate_fix_bad_hk_swap_runs_on_mainnet_genesis() { ::AccountId::decode(&mut account_id32_slice).expect("Invalid hotkey"); // Give balance to coldkey - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 100_000222.into()); + add_balance_to_coldkey_account(&coldkey_account_id, 100_000222.into()); // Give stake to hotkey let stake_added = 222222.into(); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -4422,3 +4422,40 @@ fn test_migrate_fix_root_claimed_incorrect_genesis() { ); }); } + +#[test] +fn test_migrate_subnet_balances() { + new_test_ext(1).execute_with(|| { + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + + // Add network locks + let lock1 = TaoBalance::from(123_000_000_000_u64); + let lock2 = TaoBalance::from(321_000_000_000_u64); + SubnetLocked::::insert(netuid1, lock1); + SubnetLocked::::insert(netuid2, lock2); + + // Add SubnetTAO + let reserve1 = TaoBalance::from(456_000_000_000_u64); + let reserve2 = TaoBalance::from(654_000_000_000_u64); + SubnetTAO::::insert(netuid1, reserve1); + SubnetTAO::::insert(netuid2, reserve2); + + // Run migration + crate::migrations::migrate_subnet_balances::migrate_subnet_balances::(); + + // Test that subnet balances got updated + let subnet_account_1 = SubtensorModule::get_subnet_account_id(netuid1).unwrap(); + let subnet_account_2 = SubtensorModule::get_subnet_account_id(netuid2).unwrap(); + let balance1 = SubtensorModule::get_coldkey_balance(&subnet_account_1); + let balance2 = SubtensorModule::get_coldkey_balance(&subnet_account_2); + assert_eq!(balance1, lock1 + reserve1); + assert_eq!(balance2, lock2 + reserve2); + + // Check migration has been marked as run + const MIGRATION_NAME: &[u8] = b"migrate_subnet_balances"; + assert!(HasMigrationRun::::get(MIGRATION_NAME.to_vec())); + }); +} diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index 8546b229c6..94f50e187c 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -244,6 +244,8 @@ parameter_types! { pub const LeaseDividendsDistributionInterval: u32 = 100; pub const MaxImmuneUidsPercentage: Percent = Percent::from_percent(80); pub const EvmKeyAssociateRateLimit: u64 = 10; + pub const SubtensorPalletId: PalletId = PalletId(*b"subtensr"); + pub const BurnAccountId: PalletId = PalletId(*b"burntnsr"); } impl crate::Config for Test { @@ -319,6 +321,8 @@ impl crate::Config for Test { type CommitmentsInterface = CommitmentsI; type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit; type AuthorshipProvider = MockAuthorshipProvider; + type SubtensorPalletId = SubtensorPalletId; + type BurnAccountId = BurnAccountId; type WeightInfo = (); } @@ -767,7 +771,7 @@ pub fn register_ok_neuron( let bal: TaoBalance = SubtensorModule::get_coldkey_balance(&cold); if bal < min_balance_needed { - SubtensorModule::add_balance_to_coldkey_account(&cold, min_balance_needed - bal); + add_balance_to_coldkey_account(&cold, min_balance_needed - bal); } }; @@ -840,7 +844,7 @@ pub fn add_network_disable_subtoken(netuid: NetUid, tempo: u16, _modality: u16) pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost.into()); + add_balance_to_coldkey_account(coldkey, lock_cost.into()); TotalIssuance::::mutate(|total_issuance| { *total_issuance = total_issuance.saturating_add(lock_cost); }); @@ -864,7 +868,7 @@ pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { pub fn add_dynamic_network_without_emission_block(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost.into()); + add_balance_to_coldkey_account(coldkey, lock_cost.into()); TotalIssuance::::mutate(|total_issuance| { *total_issuance = total_issuance.saturating_add(lock_cost); }); @@ -972,6 +976,10 @@ pub fn increase_stake_on_coldkey_hotkey_account( tao_staked: TaoBalance, netuid: NetUid, ) { + // Add TAO balance to coldkey account + add_balance_to_coldkey_account(coldkey, tao_staked.into()); + + // Stake SubtensorModule::stake_into_subnet( hotkey, coldkey, @@ -1105,6 +1113,41 @@ pub fn sf_from_u64(val: u64) -> SafeFloat { } #[allow(dead_code)] +pub fn add_balance_to_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let ed = ExistentialDeposit::get(); + if tao >= ed { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao).unwrap(); + } +} + +#[allow(dead_code)] +pub fn remove_balance_from_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let _ = SubtensorModule::burn_tao(coldkey, tao); +} + +#[allow(dead_code)] +pub fn mock_increase_stake_for_hotkey_and_coldkey_on_subnet( + hotkey: &U256, + coldkey: &U256, + netuid: NetUid, + alpha: AlphaBalance, +) { + // Record stake in alpha pool + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, alpha, + ); + + // Make sure subnet exists, so does it's account + NetworksAdded::::insert(netuid, true); + + // Add TAO balance to subnet account + // For simplicity make it equal to alpha * 100, which is more than needed + let subnet_account = SubtensorModule::get_subnet_account_id(netuid).unwrap(); + let tao_bal = u64::from(alpha) * 100; + add_balance_to_coldkey_account(&subnet_account, tao_bal.into()); +} + pub fn remove_owner_registration_stake(netuid: NetUid) { let owner_hotkey = SubnetOwnerHotkey::::get(netuid); let owner_coldkey = SubnetOwner::::get(netuid); diff --git a/pallets/subtensor/src/tests/mock_high_ed.rs b/pallets/subtensor/src/tests/mock_high_ed.rs new file mode 100644 index 0000000000..4ad8d854dd --- /dev/null +++ b/pallets/subtensor/src/tests/mock_high_ed.rs @@ -0,0 +1,572 @@ +#![allow( + clippy::arithmetic_side_effects, + clippy::expect_used, + clippy::unwrap_used +)] + +use core::num::NonZeroU64; + +use crate::*; +use frame_support::traits::{Everything, InherentBuilder, InstanceFilter}; +use frame_support::weights::Weight; +use frame_support::weights::constants::RocksDbWeight; +use frame_support::{PalletId, derive_impl}; +use frame_support::{parameter_types, traits::PrivilegeCmp}; +use frame_system as system; +use frame_system::{EnsureRoot, limits, offchain::CreateTransactionBase}; +use pallet_subtensor_proxy as pallet_proxy; +use sp_core::{ConstU64, H256, U256, offchain::KeyTypeId}; +use sp_runtime::Perbill; +use sp_runtime::{ + BuildStorage, Percent, + traits::{BlakeTwo256, IdentityLookup}, +}; +use sp_std::{cmp::Ordering, sync::OnceLock}; +use sp_tracing::tracing_subscriber; +use substrate_fixed::types::U64F64; +use subtensor_runtime_common::{AuthorshipInfo, NetUid, TaoBalance}; +use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt}; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system = 1, + Balances: pallet_balances = 2, + Shield: pallet_shield = 3, + SubtensorModule: crate = 4, + Scheduler: pallet_scheduler = 5, + Preimage: pallet_preimage = 6, + Drand: pallet_drand = 7, + Swap: pallet_subtensor_swap = 8, + Crowdloan: pallet_crowdloan = 9, + Proxy: pallet_subtensor_proxy = 10, + } +); + +#[allow(dead_code)] +pub type TestRuntimeCall = frame_system::Call; + +pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"test"); + +#[allow(dead_code)] +pub type AccountId = U256; + +// The address format for describing accounts. +#[allow(dead_code)] +pub type Address = AccountId; + +// Balance of an account. +#[allow(dead_code)] +pub type Balance = TaoBalance; + +// An index to a block. +#[allow(dead_code)] +pub type BlockNumber = u64; + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] +impl pallet_balances::Config for Test { + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type MaxLocks = (); + type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = (); + type RuntimeHoldReason = (); + type FreezeIdentifier = (); + type MaxFreezes = (); +} + +impl pallet_shield::Config for Test { + type AuthorityId = sp_core::sr25519::Public; + type FindAuthors = (); + type WeightInfo = (); +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = BlockWeights; + type BlockLength = (); + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = U256; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type Nonce = u64; + type Block = Block; + type DispatchExtension = crate::CheckColdkeySwap; +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +pub const MOCK_BLOCK_BUILDER: u64 = 12345u64; + +pub struct MockAuthorshipProvider; + +impl AuthorshipInfo for MockAuthorshipProvider { + fn author() -> Option { + Some(U256::from(MOCK_BLOCK_BUILDER)) + } +} + +parameter_types! { + pub const InitialMinAllowedWeights: u16 = 0; + pub const InitialEmissionValue: u16 = 0; + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::with_sensible_defaults( + Weight::from_parts(2_000_000_000_000, u64::MAX), + Perbill::from_percent(75), + ); + pub const ExistentialDeposit: Balance = TaoBalance::new(100); + pub const TransactionByteFee: Balance = TaoBalance::new(100); + pub const SDebug:u64 = 1; + pub const InitialRho: u16 = 30; + pub const InitialAlphaSigmoidSteepness: i16 = 1000; + pub const InitialKappa: u16 = 32_767; + pub const InitialTempo: u16 = 360; + pub const SelfOwnership: u64 = 2; + pub const InitialImmunityPeriod: u16 = 2; + pub const InitialMinAllowedUids: u16 = 2; + pub const InitialMaxAllowedUids: u16 = 256; + pub const InitialBondsMovingAverage: u64 = 900_000; + pub const InitialBondsPenalty:u16 = u16::MAX; + pub const InitialBondsResetOn: bool = false; + pub const InitialStakePruningMin: u16 = 0; + pub const InitialFoundationDistribution: u64 = 0; + pub const InitialDefaultDelegateTake: u16 = 11_796; // 18%, same as in production + pub const InitialMinDelegateTake: u16 = 5_898; // 9%; + pub const InitialDefaultChildKeyTake: u16 = 0 ;// 0 % + pub const InitialMinChildKeyTake: u16 = 0; // 0 %; + pub const InitialMaxChildKeyTake: u16 = 11_796; // 18 %; + pub const InitialWeightsVersionKey: u16 = 0; + pub const InitialServingRateLimit: u64 = 0; // No limit. + pub const InitialTxRateLimit: u64 = 0; // Disable rate limit for testing + pub const InitialTxDelegateTakeRateLimit: u64 = 1; // 1 block take rate limit for testing + pub const InitialTxChildKeyTakeRateLimit: u64 = 1; // 1 block take rate limit for testing + pub const InitialBurn: u64 = 0; + pub const InitialMinBurn: u64 = 500_000; + pub const InitialMaxBurn: u64 = 1_000_000_000; + pub const MinBurnUpperBound: TaoBalance = TaoBalance::new(1_000_000_000); // 1 TAO + pub const MaxBurnLowerBound: TaoBalance = TaoBalance::new(100_000_000); // 0.1 TAO + pub const InitialValidatorPruneLen: u64 = 0; + pub const InitialScalingLawPower: u16 = 50; + pub const InitialMaxAllowedValidators: u16 = 100; + pub const InitialIssuance: u64 = 0; + pub const InitialDifficulty: u64 = 10000; + pub const InitialActivityCutoff: u16 = 5000; + pub const InitialAdjustmentInterval: u16 = 100; + pub const InitialAdjustmentAlpha: u64 = 0; // no weight to previous value. + pub const InitialMaxRegistrationsPerBlock: u16 = 3; + pub const InitialTargetRegistrationsPerInterval: u16 = 2; + pub const InitialPruningScore : u16 = u16::MAX; + pub const InitialRegistrationRequirement: u16 = u16::MAX; // Top 100% + pub const InitialMinDifficulty: u64 = 1; + pub const InitialMaxDifficulty: u64 = u64::MAX; + pub const InitialRAORecycledForRegistration: u64 = 0; + pub const InitialNetworkImmunityPeriod: u64 = 1_296_000; + pub const InitialNetworkMinLockCost: u64 = 100_000_000_000; + pub const InitialSubnetOwnerCut: u16 = 0; // 0%. 100% of rewards go to validators + miners. + pub const InitialNetworkLockReductionInterval: u64 = 2; // 2 blocks. + pub const InitialNetworkRateLimit: u64 = 0; + pub const InitialKeySwapCost: u64 = 1_000_000_000; + pub const InitialAlphaHigh: u16 = 58982; // Represents 0.9 as per the production default + pub const InitialAlphaLow: u16 = 45875; // Represents 0.7 as per the production default + pub const InitialLiquidAlphaOn: bool = false; // Default value for LiquidAlphaOn + pub const InitialYuma3On: bool = false; // Default value for Yuma3On + pub const InitialColdkeySwapAnnouncementDelay: u64 = 50; + pub const InitialColdkeySwapReannouncementDelay: u64 = 10; + pub const InitialDissolveNetworkScheduleDuration: u64 = 5 * 24 * 60 * 60 / 12; // Default as 5 days + pub const InitialTaoWeight: u64 = 0; // 100% global weight. + pub const InitialEmaPriceHalvingPeriod: u64 = 201_600_u64; // 4 weeks + pub const InitialStartCallDelay: u64 = 0; // 0 days + pub const InitialKeySwapOnSubnetCost: u64 = 10_000_000; + pub const HotkeySwapOnSubnetInterval: u64 = 15; // 15 block, should be bigger than subnet number, then trigger clean up for all subnets + pub const MaxContributorsPerLeaseToRemove: u32 = 3; + pub const LeaseDividendsDistributionInterval: u32 = 100; + pub const MaxImmuneUidsPercentage: Percent = Percent::from_percent(80); + pub const EvmKeyAssociateRateLimit: u64 = 10; + pub const SubtensorPalletId: PalletId = PalletId(*b"subtensr"); + pub const BurnAccountId: PalletId = PalletId(*b"burntnsr"); +} + +impl crate::Config for Test { + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type InitialIssuance = InitialIssuance; + type SudoRuntimeCall = TestRuntimeCall; + type Scheduler = Scheduler; + type InitialMinAllowedWeights = InitialMinAllowedWeights; + type InitialEmissionValue = InitialEmissionValue; + type InitialTempo = InitialTempo; + type InitialDifficulty = InitialDifficulty; + type InitialAdjustmentInterval = InitialAdjustmentInterval; + type InitialAdjustmentAlpha = InitialAdjustmentAlpha; + type InitialTargetRegistrationsPerInterval = InitialTargetRegistrationsPerInterval; + type InitialRho = InitialRho; + type InitialAlphaSigmoidSteepness = InitialAlphaSigmoidSteepness; + type InitialKappa = InitialKappa; + type InitialMinAllowedUids = InitialMinAllowedUids; + type InitialMaxAllowedUids = InitialMaxAllowedUids; + type InitialValidatorPruneLen = InitialValidatorPruneLen; + type InitialScalingLawPower = InitialScalingLawPower; + type InitialImmunityPeriod = InitialImmunityPeriod; + type InitialActivityCutoff = InitialActivityCutoff; + type InitialMaxRegistrationsPerBlock = InitialMaxRegistrationsPerBlock; + type InitialPruningScore = InitialPruningScore; + type InitialBondsMovingAverage = InitialBondsMovingAverage; + type InitialBondsPenalty = InitialBondsPenalty; + type InitialBondsResetOn = InitialBondsResetOn; + type InitialMaxAllowedValidators = InitialMaxAllowedValidators; + type InitialDefaultDelegateTake = InitialDefaultDelegateTake; + type InitialMinDelegateTake = InitialMinDelegateTake; + type InitialDefaultChildKeyTake = InitialDefaultChildKeyTake; + type InitialMinChildKeyTake = InitialMinChildKeyTake; + type InitialMaxChildKeyTake = InitialMaxChildKeyTake; + type InitialTxChildKeyTakeRateLimit = InitialTxChildKeyTakeRateLimit; + type InitialWeightsVersionKey = InitialWeightsVersionKey; + type InitialMaxDifficulty = InitialMaxDifficulty; + type InitialMinDifficulty = InitialMinDifficulty; + type InitialServingRateLimit = InitialServingRateLimit; + type InitialTxRateLimit = InitialTxRateLimit; + type InitialTxDelegateTakeRateLimit = InitialTxDelegateTakeRateLimit; + type InitialBurn = InitialBurn; + type InitialMaxBurn = InitialMaxBurn; + type InitialMinBurn = InitialMinBurn; + type MinBurnUpperBound = MinBurnUpperBound; + type MaxBurnLowerBound = MaxBurnLowerBound; + type InitialRAORecycledForRegistration = InitialRAORecycledForRegistration; + type InitialNetworkImmunityPeriod = InitialNetworkImmunityPeriod; + type InitialNetworkMinLockCost = InitialNetworkMinLockCost; + type InitialSubnetOwnerCut = InitialSubnetOwnerCut; + type InitialNetworkLockReductionInterval = InitialNetworkLockReductionInterval; + type InitialNetworkRateLimit = InitialNetworkRateLimit; + type KeySwapCost = InitialKeySwapCost; + type AlphaHigh = InitialAlphaHigh; + type AlphaLow = InitialAlphaLow; + type LiquidAlphaOn = InitialLiquidAlphaOn; + type Yuma3On = InitialYuma3On; + type Preimages = Preimage; + type InitialColdkeySwapAnnouncementDelay = InitialColdkeySwapAnnouncementDelay; + type InitialColdkeySwapReannouncementDelay = InitialColdkeySwapReannouncementDelay; + type InitialDissolveNetworkScheduleDuration = InitialDissolveNetworkScheduleDuration; + type InitialTaoWeight = InitialTaoWeight; + type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod; + type InitialStartCallDelay = InitialStartCallDelay; + type SwapInterface = pallet_subtensor_swap::Pallet; + type KeySwapOnSubnetCost = InitialKeySwapOnSubnetCost; + type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval; + type ProxyInterface = (); + type LeaseDividendsDistributionInterval = LeaseDividendsDistributionInterval; + type GetCommitments = (); + type MaxImmuneUidsPercentage = MaxImmuneUidsPercentage; + type CommitmentsInterface = CommitmentsI; + type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit; + type AuthorshipProvider = MockAuthorshipProvider; + type SubtensorPalletId = SubtensorPalletId; + type BurnAccountId = BurnAccountId; + type WeightInfo = (); +} + +// Swap-related parameter types +parameter_types! { + pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap"); + pub const SwapMaxFeeRate: u16 = 10000; // 15.26% + pub const SwapMaxPositions: u32 = 100; + pub const SwapMinimumLiquidity: u64 = 1_000; + pub const SwapMinimumReserve: NonZeroU64 = NonZeroU64::new(100).unwrap(); +} + +impl pallet_subtensor_swap::Config for Test { + type SubnetInfo = SubtensorModule; + type BalanceOps = SubtensorModule; + type ProtocolId = SwapProtocolId; + type TaoReserve = TaoBalanceReserve; + type AlphaReserve = AlphaBalanceReserve; + type MaxFeeRate = SwapMaxFeeRate; + type MaxPositions = SwapMaxPositions; + type MinimumLiquidity = SwapMinimumLiquidity; + type MinimumReserve = SwapMinimumReserve; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + +pub struct OriginPrivilegeCmp; + +impl PrivilegeCmp for OriginPrivilegeCmp { + fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option { + Some(Ordering::Less) + } +} + +pub struct CommitmentsI; +impl CommitmentsInterface for CommitmentsI { + fn purge_netuid(_netuid: NetUid) {} +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * + BlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 50; + pub const NoPreimagePostponement: Option = Some(10); +} + +impl pallet_scheduler::Config for Test { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = MaxScheduledPerBlock; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type OriginPrivilegeCmp = OriginPrivilegeCmp; + type Preimages = Preimage; + type BlockNumberProvider = System; +} + +parameter_types! { + pub const PreimageMaxSize: u32 = 4096 * 1024; + pub const PreimageBaseDeposit: Balance = TaoBalance::new(1); + pub const PreimageByteDeposit: Balance = TaoBalance::new(1); +} + +impl pallet_preimage::Config for Test { + type WeightInfo = pallet_preimage::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type Consideration = (); +} + +parameter_types! { + pub const CrowdloanPalletId: PalletId = PalletId(*b"bt/cloan"); + pub const MinimumDeposit: u64 = 50; + pub const AbsoluteMinimumContribution: u64 = 10; + pub const MinimumBlockDuration: u64 = 20; + pub const MaximumBlockDuration: u64 = 100; + pub const RefundContributorsLimit: u32 = 5; + pub const MaxContributors: u32 = 10; +} + +impl pallet_crowdloan::Config for Test { + type PalletId = CrowdloanPalletId; + type Currency = Balances; + type RuntimeCall = RuntimeCall; + type WeightInfo = pallet_crowdloan::weights::SubstrateWeight; + type Preimages = Preimage; + type MinimumDeposit = MinimumDeposit; + type AbsoluteMinimumContribution = AbsoluteMinimumContribution; + type MinimumBlockDuration = MinimumBlockDuration; + type MaximumBlockDuration = MaximumBlockDuration; + type RefundContributorsLimit = RefundContributorsLimit; + type MaxContributors = MaxContributors; +} + +// Proxy Pallet config +parameter_types! { + // Set as 1 for testing purposes + pub const ProxyDepositBase: Balance = TaoBalance::new(1); + // Set as 1 for testing purposes + pub const ProxyDepositFactor: Balance = TaoBalance::new(1); + // Set as 20 for testing purposes + pub const MaxProxies: u32 = 20; // max num proxies per acct + // Set as 15 for testing purposes + pub const MaxPending: u32 = 15; // max blocks pending ~15min + // Set as 1 for testing purposes + pub const AnnouncementDepositBase: Balance = TaoBalance::new(1); + // Set as 1 for testing purposes + pub const AnnouncementDepositFactor: Balance = TaoBalance::new(1); +} + +impl pallet_proxy::Config for Test { + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = subtensor_runtime_common::ProxyType; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type MaxProxies = MaxProxies; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type MaxPending = MaxPending; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; + type BlockNumberProvider = System; +} + +impl InstanceFilter for subtensor_runtime_common::ProxyType { + fn filter(&self, _c: &RuntimeCall) -> bool { + // In tests, allow all proxy types to pass through + true + } + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (subtensor_runtime_common::ProxyType::Any, _) => true, + _ => false, + } + } +} + +mod test_crypto { + use super::KEY_TYPE; + use sp_core::{ + U256, + sr25519::{Public as Sr25519Public, Signature as Sr25519Signature}, + }; + use sp_runtime::{ + app_crypto::{app_crypto, sr25519}, + traits::IdentifyAccount, + }; + + app_crypto!(sr25519, KEY_TYPE); + + pub struct TestAuthId; + + impl frame_system::offchain::AppCrypto for TestAuthId { + type RuntimeAppPublic = Public; + type GenericSignature = Sr25519Signature; + type GenericPublic = Sr25519Public; + } + + impl IdentifyAccount for Public { + type AccountId = U256; + + fn into_account(self) -> U256 { + let mut bytes = [0u8; 32]; + bytes.copy_from_slice(self.as_ref()); + U256::from_big_endian(&bytes) + } + } +} + +pub type TestAuthId = test_crypto::TestAuthId; + +impl pallet_drand::Config for Test { + type AuthorityId = TestAuthId; + type Verifier = pallet_drand::verifier::QuicknetVerifier; + type UnsignedPriority = ConstU64<{ 1 << 20 }>; + type HttpFetchTimeout = ConstU64<1_000>; + type WeightInfo = (); +} + +impl frame_system::offchain::SigningTypes for Test { + type Public = test_crypto::Public; + type Signature = test_crypto::Signature; +} + +pub type UncheckedExtrinsic = sp_runtime::testing::TestXt; + +impl frame_system::offchain::CreateTransactionBase for Test +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type RuntimeCall = RuntimeCall; +} + +impl frame_system::offchain::CreateInherent for Test +where + RuntimeCall: From, +{ + fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic { + UncheckedExtrinsic::new_inherent(call) + } +} + +impl frame_system::offchain::CreateSignedTransaction for Test +where + RuntimeCall: From, +{ + fn create_signed_transaction< + C: frame_system::offchain::AppCrypto, + >( + call: >::RuntimeCall, + _public: Self::Public, + _account: Self::AccountId, + nonce: Self::Nonce, + ) -> Option { + Some(UncheckedExtrinsic::new_signed(call, nonce.into(), (), ())) + } +} + +static TEST_LOGS_INIT: OnceLock<()> = OnceLock::new(); + +pub fn init_logs_for_tests() { + if TEST_LOGS_INIT.get().is_some() { + return; + } + + // RUST_LOG (full syntax) or "off" if unset + let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("off")); + + // Bridge log -> tracing (ok if already set) + let _ = tracing_log::LogTracer::init(); + + // Simple formatter + let fmt_layer = tracing_subscriber::fmt::layer() + .with_ansi(false) + .with_target(true) + .with_level(true) + .without_time(); + + let _ = tracing_subscriber::registry() + .with(filter) + .with(fmt_layer) + .try_init(); + + let _ = TEST_LOGS_INIT.set(()); +} + +#[allow(dead_code)] +// Build genesis storage according to the mock runtime. +pub fn new_test_ext(block_number: BlockNumber) -> sp_io::TestExternalities { + init_logs_for_tests(); + let t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(block_number)); + ext +} + +#[allow(dead_code)] +pub fn add_network(netuid: NetUid, tempo: u16, _modality: u16) { + SubtensorModule::init_new_network(netuid, tempo); + SubtensorModule::set_network_registration_allowed(netuid, true); + FirstEmissionBlockNumber::::insert(netuid, 1); + SubtokenEnabled::::insert(netuid, true); + + // make interval 1 block so tests can register by stepping 1 block. + BurnHalfLife::::insert(netuid, 1); + BurnIncreaseMult::::insert(netuid, U64F64::from_num(1)); +} + +#[allow(dead_code)] +pub fn add_balance_to_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let ed = ExistentialDeposit::get(); + if tao >= ed { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao).unwrap(); + } +} diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index 7e0c477c56..4ccd816aec 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -15,6 +15,7 @@ mod math; mod mechanism; mod migration; pub(crate) mod mock; +pub(crate) mod mock_high_ed; mod move_stake; mod networks; mod neuron_info; @@ -28,6 +29,7 @@ mod subnet_emissions; mod swap_coldkey; mod swap_hotkey; mod swap_hotkey_with_subnet; +mod tao; mod uids; mod voting_power; mod weights; diff --git a/pallets/subtensor/src/tests/move_stake.rs b/pallets/subtensor/src/tests/move_stake.rs index 294dc79661..a991df20a5 100644 --- a/pallets/subtensor/src/tests/move_stake.rs +++ b/pallets/subtensor/src/tests/move_stake.rs @@ -26,8 +26,9 @@ fn test_do_move_success() { let stake_amount = DefaultMinStake::::get() * 10.into(); // Set up initial stake - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -78,7 +79,7 @@ fn test_do_move_success() { // 2. test_do_move_different_subnets // Description: Test moving stake between two hotkeys in different subnets -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test move -- test_do_move_different_subnets --exact --nocapture +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::move_stake::test_do_move_different_subnets --exact --show-output --nocapture #[test] fn test_do_move_different_subnets() { new_test_ext(1).execute_with(|| { @@ -103,8 +104,9 @@ fn test_do_move_different_subnets() { ); // Set up initial stake and subnets - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -173,6 +175,7 @@ fn test_do_move_nonexistent_subnet() { mock::setup_reserves(origin_netuid, reserve.into(), reserve.into()); // Set up initial stake + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -269,14 +272,17 @@ fn test_do_move_nonexistent_destination_hotkey() { let coldkey = U256::from(1); let origin_hotkey = U256::from(2); let nonexistent_destination_hotkey = U256::from(99); // Assuming this hotkey doesn't exist - let netuid = NetUid::from(1); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let stake_amount = 1_000_000; let reserve = stake_amount * 1000; mock::setup_reserves(netuid, reserve.into(), reserve.into()); // Set up initial stake - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); let alpha = SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -342,6 +348,7 @@ fn test_do_move_partial_stake() { let total_stake = DefaultMinStake::::get().to_u64() * 20; // Set up initial stake + add_balance_to_coldkey_account(&coldkey, total_stake.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -360,8 +367,9 @@ fn test_do_move_partial_stake() { // Move partial stake let alpha_moved = AlphaBalance::from(alpha.to_u64() * portion_moved / 10); - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = + SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -409,8 +417,9 @@ fn test_do_move_multiple_times() { let initial_stake = DefaultMinStake::::get().to_u64() * 10; // Set up initial stake - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey1); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey2); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey1); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey2); + add_balance_to_coldkey_account(&coldkey, initial_stake.into()); SubtensorModule::stake_into_subnet( &hotkey1, &coldkey, @@ -476,13 +485,16 @@ fn test_do_move_wrong_origin() { let wrong_coldkey = U256::from(99); let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); - let netuid = NetUid::from(1); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let stake_amount = DefaultMinStake::::get().to_u64() * 10; let reserve = stake_amount * 1000; mock::setup_reserves(netuid, reserve.into(), reserve.into()); // Set up initial stake + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -501,8 +513,8 @@ fn test_do_move_wrong_origin() { // Attempt to move stake with wrong origin add_network(netuid, 1, 0); - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); assert_err!( SubtensorModule::do_move_stake( RuntimeOrigin::signed(wrong_coldkey), @@ -549,7 +561,8 @@ fn test_do_move_same_hotkey_fails() { let stake_amount = DefaultMinStake::::get().to_u64() * 10; // Set up initial stake - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -599,8 +612,9 @@ fn test_do_move_event_emission() { let stake_amount = DefaultMinStake::::get().to_u64() * 10; // Set up initial stake - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -662,6 +676,7 @@ fn test_do_move_storage_updates() { let stake_amount = DefaultMinStake::::get().to_u64() * 10; // Set up initial stake + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, &coldkey, @@ -674,8 +689,8 @@ fn test_do_move_storage_updates() { .unwrap(); // Move stake - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -725,8 +740,9 @@ fn test_move_full_amount_same_netuid() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); // Set up initial stake SubtensorModule::stake_into_subnet( @@ -790,8 +806,9 @@ fn test_do_move_max_values() { let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); // Set up initial stake with maximum value - SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + add_balance_to_coldkey_account(&coldkey, max_stake.into()); // Add lots of liquidity to bypass low liquidity check let reserve = u64::MAX / 1000; @@ -859,10 +876,7 @@ fn test_moving_too_little_unstakes() { let (_, fee) = mock::swap_tao_to_alpha(netuid, amount); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - amount + (fee * 2).into(), - ); + add_balance_to_coldkey_account(&coldkey_account_id, amount + (fee * 2).into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), @@ -901,8 +915,9 @@ fn test_do_transfer_success() { let stake_amount = DefaultMinStake::::get().to_u64() * 10; // 3. Set up initial stake: (origin_coldkey, hotkey) on netuid. - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, @@ -1011,7 +1026,8 @@ fn test_do_transfer_insufficient_stake() { let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, @@ -1051,11 +1067,8 @@ fn test_do_transfer_wrong_origin() { let stake_amount = DefaultMinStake::::get().to_u64() * 10; let fee: u64 = 0; // FIXME: DefaultStakingFee is deprecated - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::add_balance_to_coldkey_account( - &origin_coldkey, - (stake_amount + fee).into(), - ); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, (stake_amount + fee).into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, @@ -1093,7 +1106,8 @@ fn test_do_transfer_minimum_stake_check() { let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get(); - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, @@ -1135,11 +1149,11 @@ fn test_do_transfer_different_subnets() { let stake_amount = DefaultMinStake::::get().to_u64() * 10; // 3. Create accounts if needed. - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); // 4. Deposit free balance so transaction fees do not reduce staked funds. - SubtensorModule::add_balance_to_coldkey_account(&origin_coldkey, 1_000_000_000.into()); + add_balance_to_coldkey_account(&origin_coldkey, 1_000_000_000.into()); // 5. Stake into the origin subnet. SubtensorModule::stake_into_subnet( @@ -1207,7 +1221,8 @@ fn test_do_swap_success() { let hotkey = U256::from(2); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1262,7 +1277,7 @@ fn test_do_swap_nonexistent_subnet() { let nonexistent_netuid2 = NetUid::from(9999); let stake_amount = 1_000_000; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); assert_noop!( SubtensorModule::do_swap_stake( @@ -1315,7 +1330,8 @@ fn test_do_swap_insufficient_stake() { let stake_amount = DefaultMinStake::::get().to_u64() * 5; let attempted_swap = stake_amount * 2; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1350,7 +1366,8 @@ fn test_do_swap_wrong_origin() { let hotkey = U256::from(3); let stake_amount = 100_000; - SubtensorModule::create_account_if_non_existent(&real_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&real_coldkey, &hotkey); + add_balance_to_coldkey_account(&real_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &real_coldkey, @@ -1388,7 +1405,8 @@ fn test_do_swap_minimum_stake_check() { let total_stake = DefaultMinStake::::get(); let swap_amount = 1; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, total_stake); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1424,7 +1442,8 @@ fn test_do_swap_same_subnet() { let hotkey = U256::from(2); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1469,7 +1488,8 @@ fn test_do_swap_partial_stake() { let hotkey = U256::from(2); let total_stake_tao = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, total_stake_tao.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1521,7 +1541,8 @@ fn test_do_swap_storage_updates() { let hotkey = U256::from(2); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1581,7 +1602,8 @@ fn test_do_swap_multiple_times() { let hotkey = U256::from(2); let initial_stake = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, initial_stake.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1652,7 +1674,8 @@ fn test_do_swap_allows_non_owned_hotkey() { let foreign_coldkey = U256::from(3); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&foreign_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&foreign_coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -1730,10 +1753,7 @@ fn test_move_stake_specific_stake_into_subnet_fail() { SubnetTAO::::insert(netuid, tao_in); // Give TAO balance to coldkey - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - (tao_staked + 1_000_000_000).into(), - ); + add_balance_to_coldkey_account(&coldkey_account_id, (tao_staked + 1_000_000_000).into()); // Setup Subnet pool for origin netuid SubnetAlphaIn::::insert(origin_netuid, alpha_in + 10_000_000.into()); @@ -1799,8 +1819,9 @@ fn test_transfer_stake_rate_limited() { let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, @@ -1844,8 +1865,9 @@ fn test_transfer_stake_doesnt_limit_destination_coldkey() { let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, @@ -1891,7 +1913,8 @@ fn test_swap_stake_limits_destination_netuid() { let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); + add_balance_to_coldkey_account(&origin_coldkey, stake_amount.into()); SubtensorModule::stake_into_subnet( &hotkey, &origin_coldkey, diff --git a/pallets/subtensor/src/tests/networks.rs b/pallets/subtensor/src/tests/networks.rs index fdab84d9c4..1eb00532b1 100644 --- a/pallets/subtensor/src/tests/networks.rs +++ b/pallets/subtensor/src/tests/networks.rs @@ -1,4 +1,4 @@ -#![allow(clippy::expect_used, clippy::indexing_slicing)] +#![allow(clippy::expect_used, clippy::indexing_slicing, clippy::unwrap_used)] use super::mock::*; use crate::migrations::migrate_network_immunity_period; @@ -31,14 +31,8 @@ fn test_registration_ok() { ); // registration economics changed. Ensure the coldkey has enough spendable balance - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - TaoBalance::from(reserve), - ); - SubtensorModule::add_balance_to_coldkey_account( - &hotkey_account_id, - TaoBalance::from(reserve), - ); + add_balance_to_coldkey_account(&coldkey_account_id, TaoBalance::from(reserve)); + add_balance_to_coldkey_account(&hotkey_account_id, TaoBalance::from(reserve)); let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, @@ -241,7 +235,7 @@ fn dissolve_owner_cut_refund_logic() { // One staker and a TAO pot (not relevant to refund amount). let sh = U256::from(77); let sc = U256::from(88); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &sh, &sc, net, @@ -680,6 +674,10 @@ fn dissolve_decrements_total_networks() { let hot = U256::from(42); let net = add_dynamic_network(&hot, &cold); + // Add 100 TAO to subnet account (lock) + let subnet_account = SubtensorModule::get_subnet_account_id(net).unwrap(); + add_balance_to_coldkey_account(&subnet_account, 100_000_000_000_u64.into()); + // Sanity: adding network increments the counter. assert_eq!(TotalNetworks::::get(), total_before + 1); @@ -754,8 +752,8 @@ fn destroy_alpha_out_multiple_stakers_pro_rata() { let s1: u64 = 3u64 * min_total_u64; let s2: u64 = 7u64 * min_total_u64; - SubtensorModule::add_balance_to_coldkey_account(&c1, (s1 + 50_000).into()); - SubtensorModule::add_balance_to_coldkey_account(&c2, (s2 + 50_000).into()); + add_balance_to_coldkey_account(&c1, (s1 + 50_000).into()); + add_balance_to_coldkey_account(&c2, (s2 + 50_000).into()); assert_ok!(SubtensorModule::do_add_stake( RuntimeOrigin::signed(c1), @@ -866,7 +864,7 @@ fn destroy_alpha_out_many_stakers_complex_distribution() { stake[i] = (i as u64 + 1u64) * min_amount_u64; // multiples of min_amount register_ok_neuron(netuid, hot[i], cold[i], 0); - SubtensorModule::add_balance_to_coldkey_account(&cold[i], (stake[i] + 100_000).into()); + add_balance_to_coldkey_account(&cold[i], (stake[i] + 100_000).into()); assert_ok!(SubtensorModule::do_add_stake( RuntimeOrigin::signed(cold[i]), @@ -993,7 +991,7 @@ fn destroy_alpha_out_refund_gating_by_registration_block() { // give some stake to other key let other_cold = U256::from(1_234); let other_hot = U256::from(2_345); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &other_hot, &other_cold, netuid, @@ -1059,7 +1057,7 @@ fn destroy_alpha_out_refund_gating_by_registration_block() { // give some stake to other key let other_cold = U256::from(1_234); let other_hot = U256::from(2_345); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &other_hot, &other_cold, netuid, @@ -1230,6 +1228,20 @@ fn prune_selection_complex_state_exhaustive() { System::set_block_number(imm + 6); let n6 = add_dynamic_network(&U256::from(106), &U256::from(206)); // immune at first + // Add 100 TAO to subnet accounts (lock) + let subnet_account1 = SubtensorModule::get_subnet_account_id(n1).unwrap(); + let subnet_account2 = SubtensorModule::get_subnet_account_id(n2).unwrap(); + let subnet_account3 = SubtensorModule::get_subnet_account_id(n3).unwrap(); + let subnet_account4 = SubtensorModule::get_subnet_account_id(n4).unwrap(); + let subnet_account5 = SubtensorModule::get_subnet_account_id(n5).unwrap(); + let subnet_account6 = SubtensorModule::get_subnet_account_id(n6).unwrap(); + add_balance_to_coldkey_account(&subnet_account1, 100_000_000_000_u64.into()); + add_balance_to_coldkey_account(&subnet_account2, 100_000_000_000_u64.into()); + add_balance_to_coldkey_account(&subnet_account3, 100_000_000_000_u64.into()); + add_balance_to_coldkey_account(&subnet_account4, 100_000_000_000_u64.into()); + add_balance_to_coldkey_account(&subnet_account5, 100_000_000_000_u64.into()); + add_balance_to_coldkey_account(&subnet_account6, 100_000_000_000_u64.into()); + // (Root is ignored by the selector.) let root = NetUid::ROOT; @@ -1338,7 +1350,7 @@ fn prune_selection_complex_state_exhaustive() { // Remove n5; now n6 (price=0) should be selected. // This validates robustness to holes / non-contiguous netuids. // --------------------------------------------------------------------- - SubtensorModule::do_dissolve_network(n5).expect("Expected not to panic"); + assert_ok!(SubtensorModule::do_dissolve_network(n5)); assert_eq!( SubtensorModule::get_network_to_prune(), Some(n6), @@ -1403,6 +1415,12 @@ fn register_network_prunes_and_recycles_netuid() { let n2_hot = U256::from(24); let n2 = add_dynamic_network(&n2_hot, &n2_cold); + // Add 100 TAO to subnet accounts (lock) + let subnet_account1 = SubtensorModule::get_subnet_account_id(n1).unwrap(); + add_balance_to_coldkey_account(&subnet_account1, 100_000_000_000_u64.into()); + let subnet_account2 = SubtensorModule::get_subnet_account_id(n2).unwrap(); + add_balance_to_coldkey_account(&subnet_account2, 100_000_000_000_u64.into()); + let imm = SubtensorModule::get_network_immunity_period(); System::set_block_number(imm + 100); @@ -1412,10 +1430,7 @@ fn register_network_prunes_and_recycles_netuid() { let new_cold = U256::from(30); let new_hot = U256::from(31); let needed: u64 = SubtensorModule::get_network_lock_cost().into(); - SubtensorModule::add_balance_to_coldkey_account( - &new_cold, - needed.saturating_mul(10).into(), - ); + add_balance_to_coldkey_account(&new_cold, needed.saturating_mul(10).into()); assert_ok!(SubtensorModule::do_register_network( RuntimeOrigin::signed(new_cold), @@ -1671,7 +1686,7 @@ fn test_migrate_network_immunity_period() { // let coldkey_account_id = U256::from(0); // Neighbour of the beast, har har // let new_network_owner_account_id = U256::from(2); // -// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 1000000000000000); +// add_balance_to_coldkey_account(&coldkey_account_id, 1000000000000000); // let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( // netuid, @@ -1879,7 +1894,7 @@ fn massive_dissolve_refund_and_reregistration_flow_is_lossless_and_cleans_state( // 3) LPs per net: register each (hot, cold), massive τ prefund, and stake // ──────────────────────────────────────────────────────────────────── for &cold in cold_lps.iter() { - SubtensorModule::add_balance_to_coldkey_account(&cold, u64::MAX.into()); + add_balance_to_coldkey_account(&cold, 1_000_000_000_000_u64.into()); } // τ balances before LP adds (after staking): @@ -2154,6 +2169,10 @@ fn dissolve_clears_all_mechanism_scoped_maps_for_all_mechanisms() { let owner_hot = U256::from(456); let net = add_dynamic_network(&owner_hot, &owner_cold); + // Add 100 TAO to subnet account (lock) + let subnet_account = SubtensorModule::get_subnet_account_id(net).unwrap(); + add_balance_to_coldkey_account(&subnet_account, 100_000_000_000_u64.into()); + // We'll use two mechanisms for this subnet. MechanismCountCurrent::::insert(net, MechId::from(2)); let m0 = MechId::from(0u8); @@ -2399,10 +2418,7 @@ fn register_network_credits_owner_alpha_using_fallback_price_one_on_first_subnet assert_eq!(pre_registration_median, U96F32::from_num(1u64)); assert_eq!(expected_owner_alpha_u64, lock_cost_u64); - SubtensorModule::add_balance_to_coldkey_account( - &new_cold, - lock_cost_u64.saturating_mul(2).into(), - ); + add_balance_to_coldkey_account(&new_cold, lock_cost_u64.saturating_mul(2).into()); assert_ok!(SubtensorModule::do_register_network( RuntimeOrigin::signed(new_cold), @@ -2474,10 +2490,7 @@ fn register_network_credits_owner_alpha_from_even_median_and_excludes_new_subnet owner_alpha_from_lock_and_price(lock_cost_u64, pre_registration_median); let expected_owner_alpha: AlphaBalance = expected_owner_alpha_u64.into(); - SubtensorModule::add_balance_to_coldkey_account( - &new_cold, - lock_cost_u64.saturating_mul(2).into(), - ); + add_balance_to_coldkey_account(&new_cold, lock_cost_u64.saturating_mul(2).into()); assert_ok!(SubtensorModule::do_register_network( RuntimeOrigin::signed(new_cold), @@ -2587,7 +2600,7 @@ fn register_network_non_associated_hotkey_does_not_withdraw_or_write_owner_alpha let would_be_netuid = SubtensorModule::get_next_netuid(); let lock_cost_u64: u64 = SubtensorModule::get_network_lock_cost().into(); - SubtensorModule::add_balance_to_coldkey_account(&attacker_cold, lock_cost_u64.into()); + add_balance_to_coldkey_account(&attacker_cold, lock_cost_u64.into()); let attacker_balance_before = SubtensorModule::get_coldkey_balance(&attacker_cold); assert_err!( diff --git a/pallets/subtensor/src/tests/recycle_alpha.rs b/pallets/subtensor/src/tests/recycle_alpha.rs index 39fcfcaeaa..3bd14306bf 100644 --- a/pallets/subtensor/src/tests/recycle_alpha.rs +++ b/pallets/subtensor/src/tests/recycle_alpha.rs @@ -23,7 +23,7 @@ fn test_recycle_success() { Balances::make_free_balance_be(&coldkey, initial_balance.into()); // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); assert!(SubtensorModule::if_subnet_exist(netuid)); @@ -79,7 +79,7 @@ fn test_recycle_two_stakers() { Balances::make_free_balance_be(&coldkey, initial_balance.into()); // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); assert!(SubtensorModule::if_subnet_exist(netuid)); @@ -149,7 +149,7 @@ fn test_recycle_staker_is_nominator() { Balances::make_free_balance_be(&coldkey, initial_balance.into()); // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); assert!(SubtensorModule::if_subnet_exist(netuid)); @@ -222,7 +222,7 @@ fn test_burn_success() { Balances::make_free_balance_be(&coldkey, initial_balance.into()); // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); assert!(SubtensorModule::if_subnet_exist(netuid)); @@ -278,7 +278,7 @@ fn test_burn_staker_is_nominator() { Balances::make_free_balance_be(&coldkey, initial_balance.into()); // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); assert!(SubtensorModule::if_subnet_exist(netuid)); @@ -348,7 +348,7 @@ fn test_burn_two_stakers() { Balances::make_free_balance_be(&coldkey, initial_balance.into()); // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); assert!(SubtensorModule::if_subnet_exist(netuid)); @@ -419,7 +419,7 @@ fn test_recycle_errors() { let initial_balance = 1_000_000_000; Balances::make_free_balance_be(&coldkey, initial_balance.into()); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); let stake_amount = 200_000; @@ -491,7 +491,7 @@ fn test_burn_errors() { let initial_balance = 1_000_000_000; Balances::make_free_balance_be(&coldkey, initial_balance.into()); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); register_ok_neuron(netuid, hotkey, coldkey, 0); let stake_amount = 200_000; @@ -654,7 +654,7 @@ fn test_add_stake_burn_success() { (amount * 10_000_000).into(), ); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Check we have zero staked before transfer assert_eq!( @@ -724,7 +724,7 @@ fn test_add_stake_burn_with_limit_success() { assert_eq!(current_price, U96F32::from_num(1.0)); // Give coldkey sufficient balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); let initial_balance = SubtensorModule::get_coldkey_balance(&coldkey_account_id); @@ -791,7 +791,7 @@ fn test_add_stake_burn_non_owner_fails() { ); // Give non-owner some balance - SubtensorModule::add_balance_to_coldkey_account(&non_owner_coldkey, amount.into()); + add_balance_to_coldkey_account(&non_owner_coldkey, amount.into()); // Non-owner trying to call add_stake_burn should fail with BadOrigin assert_noop!( @@ -815,7 +815,7 @@ fn test_add_stake_burn_nonexistent_subnet_fails() { let amount = DefaultMinStake::::get().to_u64() * 10; // Give some balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Try to call add_stake_burn on non-existent subnet let nonexistent_netuid = NetUid::from(999); @@ -878,7 +878,7 @@ fn test_add_stake_burn_rate_limit_exceeded() { mock::setup_reserves(netuid, tao_reserve, alpha_in); // Give coldkey sufficient balance for multiple "add stake and burn" operations. - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, (amount * 10).into()); + add_balance_to_coldkey_account(&coldkey_account_id, (amount * 10).into()); assert_eq!( SubtensorModule::get_rate_limited_last_block(&RateLimitKey::AddStakeBurn(netuid)), diff --git a/pallets/subtensor/src/tests/registration.rs b/pallets/subtensor/src/tests/registration.rs index c3cd3acb3c..6ffff0448b 100644 --- a/pallets/subtensor/src/tests/registration.rs +++ b/pallets/subtensor/src/tests/registration.rs @@ -51,7 +51,7 @@ fn test_registration_ok() { let hotkey = U256::from(1); let coldkey = U256::from(667); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 50_000.into()); + add_balance_to_coldkey_account(&coldkey, 50_000.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey), @@ -159,7 +159,7 @@ fn test_registration_not_enough_balance() { let hotkey = U256::from(1); let coldkey = U256::from(667); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 9_999.into()); + add_balance_to_coldkey_account(&coldkey, 9_999.into()); let result = SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey), @@ -189,7 +189,7 @@ fn test_registration_non_associated_coldkey() { Owner::::insert(hotkey, true_owner); // Attacker has enough funds, but doesn't own the hotkey. - SubtensorModule::add_balance_to_coldkey_account(&attacker, 50_000.into()); + add_balance_to_coldkey_account(&attacker, 50_000.into()); let result = SubtensorModule::burned_register( <::RuntimeOrigin>::signed(attacker), @@ -214,7 +214,7 @@ fn test_registration_without_neuron_slot_doesnt_burn() { let hotkey = U256::from(1); let coldkey = U256::from(667); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 10_000.into()); + add_balance_to_coldkey_account(&coldkey, 10_000.into()); let before = SubtensorModule::get_coldkey_balance(&coldkey); // No slots => should fail before burning. @@ -245,7 +245,7 @@ fn test_registration_already_active_hotkey_error() { let coldkey = U256::from(667); let hotkey = U256::from(1); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey), @@ -292,7 +292,7 @@ fn test_burn_decay() { let coldkey = U256::from(100); let hotkey = U256::from(200); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000.into()); // Register in this block. Burn updates immediately now. assert_ok!(SubtensorModule::burned_register( @@ -357,7 +357,7 @@ fn test_burn_min_and_max_clamps_prevent_zero_stuck_and_cap_bump() { // Register now; bump should apply immediately but be capped by max burn. let coldkey = U256::from(1); let hotkey = U256::from(2); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000u64.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000u64.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey), @@ -390,7 +390,7 @@ fn test_registration_increases_recycled_rao_per_subnet() { SubtensorModule::set_burn(netuid, 1_000u64.into()); let coldkey = U256::from(667); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000.into()); // First registration let burn1 = SubtensorModule::get_burn(netuid); @@ -590,7 +590,7 @@ fn test_registration_get_neuron_metadata() { let hotkey = U256::from(1); let coldkey = U256::from(667); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 100_000.into()); + add_balance_to_coldkey_account(&coldkey, 100_000.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey), @@ -629,7 +629,7 @@ fn test_last_update_correctness() { LastUpdate::::remove(NetUidStorageIndex::from(netuid)); // Give enough balance for the burn path. - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10_000.into()); + add_balance_to_coldkey_account(&coldkey_account_id, 10_000.into()); // Register and ensure LastUpdate is expanded correctly. assert_ok!(SubtensorModule::burned_register( @@ -1312,7 +1312,7 @@ fn test_burned_register_immediately_bumps_price_many_multipliers_and_same_block_ let current: u64 = SubtensorModule::get_coldkey_balance(&coldkey).into(); if current < needed { - SubtensorModule::add_balance_to_coldkey_account(&coldkey, (needed - current).into()); + add_balance_to_coldkey_account(&coldkey, (needed - current).into()); } } diff --git a/pallets/subtensor/src/tests/staking.rs b/pallets/subtensor/src/tests/staking.rs index 7a7c5b69ac..0fe951a29b 100644 --- a/pallets/subtensor/src/tests/staking.rs +++ b/pallets/subtensor/src/tests/staking.rs @@ -58,7 +58,7 @@ fn test_add_stake_ok_no_emission() { ); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Check we have zero staked before transfer assert_eq!( @@ -218,7 +218,7 @@ fn test_add_stake_not_registered_key_pair() { let hotkey_account_id = U256::from(54544); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let amount = DefaultMinStake::::get().to_u64() * 10; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); assert_err!( SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), @@ -241,7 +241,7 @@ fn test_add_stake_ok_neuron_does_not_belong_to_coldkey() { let stake = DefaultMinStake::::get() * 10.into(); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&other_cold_key, stake.into()); + add_balance_to_coldkey_account(&other_cold_key, stake.into()); // Perform the request which is signed by a different cold key assert_ok!(SubtensorModule::add_stake( @@ -287,10 +287,7 @@ fn test_add_stake_total_issuance_no_change() { // Give it some $$$ in his coldkey balance let initial_balance = 10000; - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - initial_balance.into(), - ); + add_balance_to_coldkey_account(&coldkey_account_id, initial_balance.into()); // Check we have zero staked before transfer let initial_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id); @@ -551,7 +548,7 @@ fn test_add_stake_partial_below_min_stake_fails() { // Stake TAO amount is above min stake let min_stake = DefaultMinStake::::get(); let amount = min_stake.to_u64() * 2; - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey_account_id, TaoBalance::from(amount) + ExistentialDeposit::get(), ); @@ -761,8 +758,8 @@ fn test_add_stake_insufficient_liquidity() { let amount_staked = DefaultMinStake::::get().to_u64() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked.into()); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, amount_staked.into()); // Set the liquidity at lowest possible value so that all staking requests fail let reserve = u64::from(mock::SwapMinimumReserve::get()) - 1; @@ -792,8 +789,8 @@ fn test_add_stake_insufficient_liquidity_one_side_ok() { let amount_staked = DefaultMinStake::::get().to_u64() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked.into()); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, amount_staked.into()); // Set the liquidity at lowest possible value so that all staking requests fail let reserve_alpha = u64::from(mock::SwapMinimumReserve::get()); @@ -821,8 +818,8 @@ fn test_add_stake_insufficient_liquidity_one_side_fail() { let amount_staked = DefaultMinStake::::get().to_u64() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked.into()); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, amount_staked.into()); // Set the liquidity at lowest possible value so that all staking requests fail let reserve_alpha = u64::from(mock::SwapMinimumReserve::get()) - 1; @@ -852,8 +849,8 @@ fn test_remove_stake_insufficient_liquidity() { let amount_staked = DefaultMinStake::::get().to_u64() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked.into()); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + add_balance_to_coldkey_account(&coldkey, amount_staked.into()); // Simulate stake for hotkey let reserve = u64::MAX / 1000; @@ -908,7 +905,7 @@ fn test_remove_stake_total_issuance_no_change() { pallet_subtensor_swap::FeeRate::::insert(netuid, 0); // Ensure the coldkey has at least 'amount' more balance available for staking - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); mock::setup_reserves(netuid, (amount * 100).into(), (amount * 100).into()); @@ -928,11 +925,7 @@ fn test_remove_stake_total_issuance_no_change() { let issuance_after_stake = Balances::total_issuance(); // Staking burns `amount` from balances issuance in this system design. - assert_abs_diff_eq!( - issuance_before, - issuance_after_stake + TaoBalance::from(amount), - epsilon = 1.into() - ); + assert_abs_diff_eq!(issuance_before, issuance_after_stake, epsilon = 1.into()); // Remove all stake let stake_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1019,7 +1012,7 @@ fn test_remove_prev_epoch_stake() { register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); AlphaDividendsPerSubnet::::insert(netuid, hotkey_account_id, alpha_divs); TotalHotkeyAlphaLastEpoch::::insert(hotkey_account_id, netuid, hotkey_alpha); let balance_before = SubtensorModule::get_coldkey_balance(&coldkey_account_id); @@ -1079,7 +1072,7 @@ fn test_staking_sets_div_variables() { register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Verify that divident variables are clear in the beginning assert_eq!( @@ -1151,7 +1144,7 @@ fn test_get_coldkey_balance_with_balance() { let amount = 1337; // Put the balance on the account - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); let result = SubtensorModule::get_coldkey_balance(&coldkey_account_id); @@ -1379,7 +1372,7 @@ fn test_add_balance_to_coldkey_account_ok() { new_test_ext(1).execute_with(|| { let coldkey_id = U256::from(4444322); let amount = 50000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_id, amount.into()); assert_eq!( SubtensorModule::get_coldkey_balance(&coldkey_id), amount.into() @@ -1395,17 +1388,17 @@ fn test_remove_balance_from_coldkey_account_ok() { new_test_ext(1).execute_with(|| { let coldkey_account_id = U256::from(434324); // Random let amount = 10000; // Arbitrary + let netuid = NetUid::from(1); // Put some $$ on the bank - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + NetworksAdded::::insert(netuid, true); assert_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), amount.into() ); // Should be able to withdraw without hassle - let result = SubtensorModule::remove_balance_from_coldkey_account( - &coldkey_account_id, - amount.into(), - ); + let result = + SubtensorModule::transfer_tao_to_subnet(netuid, &coldkey_account_id, amount.into()); assert!(result.is_ok()); }); } @@ -1416,13 +1409,14 @@ fn test_remove_balance_from_coldkey_account_failed() { let coldkey_account_id = U256::from(434324); // Random let amount = 10000; // Arbitrary + let netuid = NetUid::from(1); + NetworksAdded::::insert(netuid, true); + // Try to remove stake from the coldkey account. This should fail, // as there is no balance, nor does the account exist - let result = SubtensorModule::remove_balance_from_coldkey_account( - &coldkey_account_id, - amount.into(), - ); - assert_eq!(result, Err(Error::::ZeroBalanceAfterWithdrawn.into())); + let result = + SubtensorModule::transfer_tao_to_subnet(netuid, &coldkey_account_id, amount.into()); + assert_eq!(result, Err(Error::::InsufficientBalance.into())); }); } @@ -1454,7 +1448,7 @@ fn test_can_remove_balane_from_coldkey_account_ok() { let coldkey_id = U256::from(87987984); let initial_amount = 10000; let remove_amount = 5000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_id, initial_amount.into()); + add_balance_to_coldkey_account(&coldkey_id, initial_amount.into()); assert!(SubtensorModule::can_remove_balance_from_coldkey_account( &coldkey_id, remove_amount.into() @@ -1468,7 +1462,7 @@ fn test_can_remove_balance_from_coldkey_account_err_insufficient_balance() { let coldkey_id = U256::from(87987984); let initial_amount = 10000; let remove_amount = 20000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_id, initial_amount.into()); + add_balance_to_coldkey_account(&coldkey_id, initial_amount.into()); assert!(!SubtensorModule::can_remove_balance_from_coldkey_account( &coldkey_id, remove_amount.into() @@ -1689,7 +1683,7 @@ fn test_clear_small_nominations() { assert_eq!(SubtensorModule::get_owning_coldkey_for_hotkey(&hot2), cold2); // Add stake cold1 --> hot1 (non delegation.) - SubtensorModule::add_balance_to_coldkey_account(&cold1, init_balance); + add_balance_to_coldkey_account(&cold1, init_balance); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(cold1), hot1, @@ -1713,7 +1707,7 @@ fn test_clear_small_nominations() { ); // Add stake cold2 --> hot1 (is delegation.) - SubtensorModule::add_balance_to_coldkey_account(&cold2, init_balance); + add_balance_to_coldkey_account(&cold2, init_balance); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(cold2), hot1, @@ -1794,7 +1788,7 @@ fn test_delegate_take_can_be_decreased() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -1829,7 +1823,7 @@ fn test_can_set_min_take_ok() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -1861,7 +1855,7 @@ fn test_delegate_take_can_not_be_increased_with_decrease_take() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -1896,7 +1890,7 @@ fn test_delegate_take_can_be_increased() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -1931,7 +1925,7 @@ fn test_delegate_take_can_not_be_decreased_with_increase_take() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -1970,7 +1964,7 @@ fn test_delegate_take_can_be_increased_to_limit() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -2008,7 +2002,7 @@ fn test_delegate_take_can_not_be_increased_beyond_limit() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -2050,7 +2044,7 @@ fn test_rate_limits_enforced_on_increase_take() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -2110,7 +2104,7 @@ fn test_rate_limits_enforced_on_decrease_before_increase_take() { let coldkey0 = U256::from(3); // Add balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000.into()); + add_balance_to_coldkey_account(&coldkey0, 100000.into()); // Register the neuron to a new network let netuid = NetUid::from(1); @@ -2180,7 +2174,7 @@ fn test_get_total_delegated_stake_after_unstaking() { register_ok_neuron(netuid, delegate_hotkey, delegate_coldkey, 0); // Add balance to delegator - SubtensorModule::add_balance_to_coldkey_account(&delegator, initial_stake.into()); + add_balance_to_coldkey_account(&delegator, initial_stake.into()); // Delegate stake let (_, fee) = mock::swap_tao_to_alpha(netuid, initial_stake.into()); @@ -2283,7 +2277,7 @@ fn test_get_total_delegated_stake_single_delegator() { register_ok_neuron(netuid, delegate_hotkey, delegate_coldkey, 0); // Add stake from delegator - SubtensorModule::add_balance_to_coldkey_account(&delegator, stake_amount.into()); + add_balance_to_coldkey_account(&delegator, stake_amount.into()); let (_, fee) = mock::swap_tao_to_alpha(netuid, stake_amount.into()); @@ -2345,7 +2339,7 @@ fn test_get_alpha_share_stake_multiple_delegators() { register_ok_neuron(netuid, hotkey2, coldkey2, 0); // Add stake from delegator1 - SubtensorModule::add_balance_to_coldkey_account(&coldkey1, stake1 + existential_deposit); + add_balance_to_coldkey_account(&coldkey1, stake1 + existential_deposit); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey1), hotkey1, @@ -2354,7 +2348,7 @@ fn test_get_alpha_share_stake_multiple_delegators() { )); // Add stake from delegator2 - SubtensorModule::add_balance_to_coldkey_account(&coldkey2, stake2 + existential_deposit); + add_balance_to_coldkey_account(&coldkey2, stake2 + existential_deposit); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey2), hotkey2, @@ -2396,7 +2390,7 @@ fn test_get_total_delegated_stake_exclude_owner_stake() { remove_owner_registration_stake(netuid); // Add owner stake - SubtensorModule::add_balance_to_coldkey_account(&delegate_coldkey, owner_stake.into()); + add_balance_to_coldkey_account(&delegate_coldkey, owner_stake.into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(delegate_coldkey), delegate_hotkey, @@ -2405,7 +2399,7 @@ fn test_get_total_delegated_stake_exclude_owner_stake() { )); // Add delegator stake - SubtensorModule::add_balance_to_coldkey_account(&delegator, delegator_stake.into()); + add_balance_to_coldkey_account(&delegator, delegator_stake.into()); let (_, fee) = mock::swap_tao_to_alpha(netuid, delegator_stake.into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(delegator), @@ -2447,18 +2441,9 @@ fn test_mining_emission_distribution_validator_valiminer_miner() { register_ok_neuron(netuid, validator_hotkey, validator_coldkey, 0); register_ok_neuron(netuid, validator_miner_hotkey, validator_miner_coldkey, 1); register_ok_neuron(netuid, miner_hotkey, miner_coldkey, 2); - SubtensorModule::add_balance_to_coldkey_account( - &validator_coldkey, - stake + ExistentialDeposit::get(), - ); - SubtensorModule::add_balance_to_coldkey_account( - &validator_miner_coldkey, - stake + ExistentialDeposit::get(), - ); - SubtensorModule::add_balance_to_coldkey_account( - &miner_coldkey, - stake + ExistentialDeposit::get(), - ); + add_balance_to_coldkey_account(&validator_coldkey, stake + ExistentialDeposit::get()); + add_balance_to_coldkey_account(&validator_miner_coldkey, stake + ExistentialDeposit::get()); + add_balance_to_coldkey_account(&miner_coldkey, stake + ExistentialDeposit::get()); SubtensorModule::set_weights_set_rate_limit(netuid, 0); step_block(subnet_tempo); SubnetOwnerCut::::set(0); @@ -2546,7 +2531,7 @@ fn test_staking_too_little_fails() { let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Coldkey / hotkey 0 decreases take to 5%. This should fail as the minimum take is 9% assert_err!( @@ -2574,11 +2559,11 @@ fn test_add_stake_fee_goes_to_subnet_tao() { let tao_to_stake = DefaultMinStake::::get() * 10.into(); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); let subnet_tao_before = SubnetTAO::::get(netuid); // Add stake - SubtensorModule::add_balance_to_coldkey_account(&coldkey, tao_to_stake); + add_balance_to_coldkey_account(&coldkey, tao_to_stake); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -2620,11 +2605,11 @@ fn test_remove_stake_fee_goes_to_subnet_tao() { let tao_to_stake = DefaultMinStake::::get() * 10.into(); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); let subnet_tao_before = SubnetTAO::::get(netuid); // Add stake - SubtensorModule::add_balance_to_coldkey_account(&coldkey, tao_to_stake.into()); + add_balance_to_coldkey_account(&coldkey, tao_to_stake.into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -2673,7 +2658,7 @@ fn test_remove_stake_fee_realistic_values() { let alpha_divs = AlphaBalance::from(2_816_190); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + let _ = SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); // Mock a realistic scenario: // Subnet 1 has 3896 TAO and 128_011 Alpha in reserves, which @@ -2729,15 +2714,15 @@ fn test_stake_overflow() { let coldkey_account_id = U256::from(435445); let hotkey_account_id = U256::from(54544); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let amount: u64 = 21_000_000_000_000_000_u64; // Max TAO supply (test context) + let ed = u64::from(ExistentialDeposit::get()); + // Maximum possible: Max TAO supply less locked balance less ED (that's on owner's coldkey) + let amount = + 21_000_000_000_000_000_u64 - u64::from(SubtensorModule::get_network_last_lock()) - ed; register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); - // Give it some $$$ in his coldkey balance (+ED buffer to avoid reaping-related edge cases) - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - TaoBalance::from(amount) + ExistentialDeposit::get(), - ); + // Give it some $$$ in his coldkey balance + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Setup liquidity with 21M TAO values mock::setup_reserves(netuid, amount.into(), amount.into()); @@ -2754,9 +2739,10 @@ fn test_stake_overflow() { )); // Check if stake has increased properly - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - expected_alpha + expected_alpha, + epsilon = 1.into() ); // Check if total stake has increased accordingly. @@ -3786,7 +3772,7 @@ fn test_add_stake_limit_ok() { assert_eq!(current_price, U96F32::from_num(1.5)); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Setup limit price so that it doesn't peak above 4x of current price // The amount that can be executed at this price is 450 TAO only @@ -3861,7 +3847,7 @@ fn test_add_stake_limit_fill_or_kill() { assert_eq!(current_price, U96F32::from_num(1.5)); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Setup limit price so that it doesn't peak above 4x of current price // The amount that can be executed at this price is 450 TAO only @@ -3911,7 +3897,7 @@ fn test_add_stake_limit_partial_zero_max_stake_amount_error() { SubnetTAO::::insert(netuid, tao_reserve); SubnetAlphaIn::::insert(netuid, alpha_in); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); assert_noop!( SubtensorModule::add_stake_limit( @@ -3936,7 +3922,7 @@ fn test_remove_stake_limit_ok() { // add network let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey_account_id, stake_amount + ExistentialDeposit::get(), ); @@ -4096,10 +4082,7 @@ fn test_add_stake_specific_stake_into_subnet_fail() { SubnetTAO::::insert(netuid, tao_in); // Give TAO balance to coldkey - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - tao_staked + 1_000_000_000.into(), - ); + add_balance_to_coldkey_account(&coldkey_account_id, tao_staked + 1_000_000_000.into()); // Add stake as new hotkey let order = GetAlphaForTao::::with_amount(tao_staked); @@ -4149,7 +4132,7 @@ fn test_remove_99_9991_per_cent_stake_works_precisely() { pallet_subtensor_swap::FeeRate::::insert(netuid, 0); // Give it some $$$ in his coldkey balance (in addition to any leftover buffer from registration) - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Stake to hotkey account. assert_ok!(SubtensorModule::add_stake( @@ -4228,7 +4211,7 @@ fn test_remove_99_9989_per_cent_stake_leaves_a_little() { pallet_subtensor_swap::FeeRate::::insert(netuid, 0); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); + add_balance_to_coldkey_account(&coldkey_account_id, amount.into()); // Stake to hotkey account, and check if the result is ok let (_, fee) = mock::swap_tao_to_alpha(netuid, amount.into()); @@ -4419,10 +4402,7 @@ fn test_unstake_all_alpha_hits_liquidity_min() { let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey, - stake_amount + ExistentialDeposit::get(), - ); + add_balance_to_coldkey_account(&coldkey, stake_amount + ExistentialDeposit::get()); // Give the neuron some stake to remove assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey), @@ -4474,10 +4454,7 @@ fn test_unstake_all_alpha_works() { let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey, - stake_amount + ExistentialDeposit::get(), - ); + add_balance_to_coldkey_account(&coldkey, stake_amount + ExistentialDeposit::get()); // Give the neuron some stake to remove assert_ok!(SubtensorModule::add_stake( @@ -4526,10 +4503,7 @@ fn test_unstake_all_works() { let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey, - stake_amount + ExistentialDeposit::get(), - ); + add_balance_to_coldkey_account(&coldkey, stake_amount + ExistentialDeposit::get()); // Give the neuron some stake to remove assert_ok!(SubtensorModule::add_stake( @@ -4592,6 +4566,7 @@ fn test_stake_into_subnet_ok() { )); // Add stake with slippage safety and check if the result is ok + add_balance_to_coldkey_account(&coldkey, TaoBalance::MAX); assert_ok!(SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -4646,6 +4621,7 @@ fn test_stake_into_subnet_low_amount() { )); // Add stake with slippage safety and check if the result is ok + add_balance_to_coldkey_account(&coldkey, TaoBalance::MAX); assert_ok!(SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -4694,6 +4670,7 @@ fn test_unstake_from_subnet_low_amount() { )); // Add stake and check if the result is ok + add_balance_to_coldkey_account(&coldkey, TaoBalance::MAX); assert_ok!(SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -4710,6 +4687,7 @@ fn test_unstake_from_subnet_low_amount() { assert_ok!(SubtensorModule::unstake_from_subnet( &hotkey, &coldkey, + &coldkey, netuid, alpha, TaoBalance::ZERO, @@ -4734,7 +4712,7 @@ fn test_stake_into_subnet_prohibitive_limit() { // add network let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account(&coldkey, amount.into()); // Forse-set alpha in and tao reserve to make price equal 0.01 let tao_reserve = TaoBalance::from(100_000_000_000_u64); @@ -4793,7 +4771,7 @@ fn test_unstake_from_subnet_prohibitive_limit() { // add network let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account(&coldkey, amount.into()); // Forse-set alpha in and tao reserve to make price equal 0.01 let tao_reserve = TaoBalance::from(100_000_000_000_u64); @@ -4869,7 +4847,7 @@ fn test_unstake_full_amount() { // add network let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount.into()); + add_balance_to_coldkey_account(&coldkey, amount.into()); // Forse-set alpha in and tao reserve to make price equal 0.01 let tao_reserve = TaoBalance::from(100_000_000_000_u64); @@ -4977,8 +4955,8 @@ fn test_swap_fees_tao_correctness() { // add network let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, owner_balance_before); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, user_balance_before); + add_balance_to_coldkey_account(&owner_coldkey, owner_balance_before); + add_balance_to_coldkey_account(&coldkey, user_balance_before); pallet_subtensor_swap::EnabledUserLiquidity::::insert(NetUid::from(netuid), true); // Forse-set alpha in and tao reserve to make price equal 0.25 @@ -5273,8 +5251,8 @@ fn test_default_min_stake_sufficiency() { // add network let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, owner_balance_before); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, user_balance_before); + add_balance_to_coldkey_account(&owner_coldkey, owner_balance_before); + add_balance_to_coldkey_account(&coldkey, user_balance_before); let fee_rate = pallet_subtensor_swap::FeeRate::::get(NetUid::from(netuid)) as f64 / u16::MAX as f64; @@ -5320,143 +5298,6 @@ fn test_default_min_stake_sufficiency() { }); } -/// Test that modify_position always credits fees -/// -/// cargo test --package pallet-subtensor --lib -- tests::staking::test_update_position_fees --exact --show-output -#[test] -fn test_update_position_fees() { - // Test cases: add or remove liquidity during modification - [false, true].into_iter().for_each(|add| { - new_test_ext(1).execute_with(|| { - let owner_hotkey = U256::from(1); - let owner_coldkey = U256::from(2); - let coldkey = U256::from(4); - let amount = 1_000_000_000; - - // add network - let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, (amount * 10).into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, (amount * 100).into()); - pallet_subtensor_swap::EnabledUserLiquidity::::insert(NetUid::from(netuid), true); - - // Forse-set alpha in and tao reserve to make price equal 0.25 - let tao_reserve = TaoBalance::from(100_000_000_000_u64); - let alpha_in = AlphaBalance::from(400_000_000_000_u64); - mock::setup_reserves(netuid, tao_reserve, alpha_in); - - // Get the block builder balance - let block_builder = U256::from(MOCK_BLOCK_BUILDER); - let block_builder_balance_before = Balances::free_balance(block_builder); - - // Get alpha for owner - assert_ok!(SubtensorModule::add_stake( - RuntimeOrigin::signed(owner_coldkey), - owner_hotkey, - netuid, - amount.into(), - )); - - // Add owner coldkey Alpha as concentrated liquidity - // between current price current price + 0.01 - let current_price = - ::SwapInterface::current_alpha_price(netuid.into()) - .to_num::() - + 0.0001; - let limit_price = current_price + 0.001; - let tick_low = price_to_tick(current_price); - let tick_high = price_to_tick(limit_price); - let liquidity = amount; - - let (position_id, _, _) = ::SwapInterface::do_add_liquidity( - NetUid::from(netuid), - &owner_coldkey, - &owner_hotkey, - tick_low, - tick_high, - liquidity, - ) - .unwrap(); - - // Buy and then sell all alpha for user to hit owner liquidity - assert_ok!(SubtensorModule::add_stake( - RuntimeOrigin::signed(coldkey), - owner_hotkey, - netuid, - amount.into(), - )); - - remove_stake_rate_limit_for_tests(&owner_hotkey, &coldkey, netuid); - - let user_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &owner_hotkey, - &coldkey, - netuid, - ); - assert_ok!(SubtensorModule::remove_stake( - RuntimeOrigin::signed(coldkey), - owner_hotkey, - netuid, - user_alpha, - )); - - // Modify position - fees should be collected and paid to the owner (block builder is already paid by now) - let owner_tao_before = SubtensorModule::get_coldkey_balance(&owner_coldkey); - - // Make small modification - let delta = - ::MinimumLiquidity::get() - as i64 - * (if add { 1 } else { -1 }); - assert_ok!(Swap::modify_position( - RuntimeOrigin::signed(owner_coldkey), - owner_hotkey, - netuid.into(), - position_id.into(), - delta, - )); - - // Check ending owner TAO and alpha - let block_builder_balance_after_add = Balances::free_balance(block_builder); - let owner_tao_after_add = SubtensorModule::get_coldkey_balance(&owner_coldkey); - let owner_alpha_after_add = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &owner_hotkey, - &owner_coldkey, - netuid, - ); - - assert!( - owner_tao_after_add + block_builder_balance_after_add - > owner_tao_before + block_builder_balance_before - ); - - // Make small modification again - should not claim more fees - assert_ok!(Swap::modify_position( - RuntimeOrigin::signed(owner_coldkey), - owner_hotkey, - netuid.into(), - position_id.into(), - delta, - )); - - // Check ending owner TAO and alpha - let owner_tao_after_repeat = SubtensorModule::get_coldkey_balance(&owner_coldkey); - let owner_alpha_after_repeat = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &owner_hotkey, - &owner_coldkey, - netuid, - ); - - assert!(owner_tao_after_add == owner_tao_after_repeat); - if add { - assert!(owner_alpha_after_add > owner_alpha_after_repeat); - } else { - assert!(owner_alpha_after_add < owner_alpha_after_repeat); - } - }); - }); -} - #[test] fn test_stake_rate_limits() { new_test_ext(0).execute_with(|| { @@ -5474,7 +5315,7 @@ fn test_stake_rate_limits() { Delegates::::insert(hot1, SubtensorModule::get_min_delegate_take()); assert_eq!(SubtensorModule::get_owning_coldkey_for_hotkey(&hot1), cold1); - SubtensorModule::add_balance_to_coldkey_account(&cold1, init_balance); + add_balance_to_coldkey_account(&cold1, init_balance); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(cold1), hot1, @@ -5520,7 +5361,7 @@ fn test_add_root_updates_counters() { // Give it some $$$ in his coldkey balance let initial_balance = stake_amount + ExistentialDeposit::get(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, initial_balance); + add_balance_to_coldkey_account(&coldkey_account_id, initial_balance); // Setup SubnetAlphaIn (because we are going to stake) SubnetAlphaIn::::insert(NetUid::ROOT, AlphaBalance::from(stake_amount.to_u64())); @@ -5575,10 +5416,10 @@ fn test_remove_root_updates_counters() { // Give it some $$$ in his coldkey balance let initial_balance = stake_amount + ExistentialDeposit::get(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, initial_balance); + add_balance_to_coldkey_account(&coldkey_account_id, initial_balance); // Setup existing stake - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &coldkey_account_id, NetUid::ROOT, @@ -5653,6 +5494,7 @@ fn test_staking_records_flow() { .unwrap(); // Add stake with slippage safety and check if the result is ok + add_balance_to_coldkey_account(&coldkey, TaoBalance::MAX); assert_ok!(SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -5679,6 +5521,7 @@ fn test_staking_records_flow() { assert_ok!(SubtensorModule::unstake_from_subnet( &hotkey, &coldkey, + &coldkey, netuid, alpha, TaoBalance::ZERO, diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index 9d734b992a..9ed44a6cb0 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -5,6 +5,7 @@ use crate::*; use frame_support::{assert_err, assert_noop, assert_ok}; use frame_system::Config; use sp_core::U256; +use std::collections::BTreeSet; use subtensor_runtime_common::{AlphaBalance, TaoBalance}; use super::mock; @@ -70,7 +71,7 @@ fn test_do_start_call_fail_not_owner() { add_network_without_emission_block(netuid, tempo, 0); mock::setup_reserves(netuid, 1_000_000_000.into(), 1_000_000_000.into()); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000.into()); + add_balance_to_coldkey_account(&coldkey_account_id, 10000.into()); add_network_without_emission_block(netuid, tempo, 0); @@ -100,7 +101,7 @@ fn test_do_start_call_can_start_now() { add_network_without_emission_block(netuid, tempo, 0); mock::setup_reserves(netuid, 1_000_000_000.into(), 1_000_000_000.into()); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000.into()); + add_balance_to_coldkey_account(&coldkey_account_id, 10000.into()); add_network_without_emission_block(netuid, tempo, 0); @@ -132,7 +133,7 @@ fn test_do_start_call_fail_for_set_again() { // Fund coldkey based on the actual burn. let burn_u64 = SubtensorModule::get_burn(netuid); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey_account_id, burn_u64 .saturating_add(ExistentialDeposit::get()) @@ -210,7 +211,7 @@ fn test_register_network_min_burn_at_default() { let cost = SubtensorModule::get_network_lock_cost(); // Give coldkey enough for lock - SubtensorModule::add_balance_to_coldkey_account(&sn_owner_coldkey, cost.into()); + add_balance_to_coldkey_account(&sn_owner_coldkey, ExistentialDeposit::get() + cost.into()); // Register network assert_ok!(SubtensorModule::register_network( @@ -241,7 +242,7 @@ fn test_register_network_use_symbol_for_subnet_if_available() { let coldkey = U256::from(1_000_000 + i); let hotkey = U256::from(2_000_000 + i); let cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, cost.into()); + add_balance_to_coldkey_account(&coldkey, ExistentialDeposit::get() + cost.into()); assert_ok!(SubtensorModule::register_network( <::RuntimeOrigin>::signed(coldkey), @@ -260,6 +261,9 @@ fn test_register_network_use_symbol_for_subnet_if_available() { // Check registration allowed assert!(NetworkRegistrationAllowed::::get(netuid)); assert!(NetworkPowRegistrationAllowed::::get(netuid)); + + // Reduce lock cost to avoid exponential cost growth + NetworkLastLockCost::::set(1_000.into()); } }); } @@ -272,7 +276,7 @@ fn test_register_network_use_next_available_symbol_if_symbol_for_subnet_is_taken let coldkey = U256::from(1_000_000 + i); let hotkey = U256::from(2_000_000 + i); let cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, cost.into()); + add_balance_to_coldkey_account(&coldkey, ExistentialDeposit::get() + cost.into()); assert_ok!(SubtensorModule::register_network( <::RuntimeOrigin>::signed(coldkey), @@ -291,6 +295,9 @@ fn test_register_network_use_next_available_symbol_if_symbol_for_subnet_is_taken // Check registration allowed assert!(NetworkRegistrationAllowed::::get(netuid)); assert!(NetworkPowRegistrationAllowed::::get(netuid)); + + // Reduce lock cost to avoid exponential cost growth + NetworkLastLockCost::::set(1_000.into()); } // Swap some of the network symbol for the network 25 to network 51 symbol (not registered yet) @@ -300,7 +307,7 @@ fn test_register_network_use_next_available_symbol_if_symbol_for_subnet_is_taken let coldkey = U256::from(1_000_000 + 50); let hotkey = U256::from(2_000_000 + 50); let cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, cost.into()); + add_balance_to_coldkey_account(&coldkey, ExistentialDeposit::get() + cost.into()); assert_ok!(SubtensorModule::register_network( <::RuntimeOrigin>::signed(coldkey), @@ -328,19 +335,22 @@ fn test_register_network_use_default_symbol_if_all_symbols_are_taken() { let coldkey = U256::from(1_000_000 + i); let hotkey = U256::from(2_000_000 + i); let cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, cost.into()); + add_balance_to_coldkey_account(&coldkey, ExistentialDeposit::get() + cost.into()); assert_ok!(SubtensorModule::register_network( <::RuntimeOrigin>::signed(coldkey), hotkey )); + + // Reduce lock cost to avoid exponential cost growth + NetworkLastLockCost::::set(1_000.into()); } // Register a new network let coldkey = U256::from(1_000_000 + 50); let hotkey = U256::from(2_000_000 + 50); let cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, cost.into()); + add_balance_to_coldkey_account(&coldkey, ExistentialDeposit::get() + cost.into()); assert_ok!(SubtensorModule::register_network( <::RuntimeOrigin>::signed(coldkey), @@ -362,6 +372,7 @@ fn test_register_network_use_default_symbol_if_all_symbols_are_taken() { assert!(NetworkPowRegistrationAllowed::::get(netuid)); }); } + // cargo test --package pallet-subtensor --lib -- tests::subnet::test_subtoken_enable --exact --show-output #[test] fn test_subtoken_enable() { @@ -385,8 +396,7 @@ fn test_subtoken_enable() { }); } -// cargo test --package pallet-subtensor --lib -- -// tests::subnet::test_subtoken_enable_reject_trading_before_enable --exact --show-output +// cargo test --package pallet-subtensor --lib -- tests::subnet::test_subtoken_enable_reject_trading_before_enable --exact --show-output #[allow(clippy::unwrap_used)] #[test] fn test_subtoken_enable_reject_trading_before_enable() { @@ -419,10 +429,10 @@ fn test_subtoken_enable_reject_trading_before_enable() { register_ok_neuron(netuid, hotkey_account_2_id, coldkey_account_id, 0); register_ok_neuron(netuid2, hotkey_account_2_id, coldkey_account_id, 100); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10_000.into()); + add_balance_to_coldkey_account(&coldkey_account_id, 10_000.into()); // Give some stake - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + mock_increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &coldkey_account_id, netuid, @@ -592,10 +602,7 @@ fn test_subtoken_enable_trading_ok_with_enable() { register_ok_neuron(netuid, hotkey_account_2_id, coldkey_account_id, 0); register_ok_neuron(netuid2, hotkey_account_2_id, coldkey_account_id, 100); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey_account_id, - stake_amount * 10.into(), - ); + add_balance_to_coldkey_account(&coldkey_account_id, stake_amount * 10.into()); // all trading extrinsic should be possible now that subtoken is enabled. assert_ok!(SubtensorModule::add_stake( @@ -712,7 +719,7 @@ fn test_subtoken_enable_ok_for_burn_register_before_enable() { // Fund enough to burned-register twice + keep-alive buffer. let burn_1 = SubtensorModule::get_burn(netuid); let burn_2 = SubtensorModule::get_burn(netuid2); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &coldkey_account_id, burn_1 .saturating_add(burn_2) @@ -909,3 +916,63 @@ fn test_update_symbol_fails_if_symbol_already_in_use() { ); }); } + +// cargo test --package pallet-subtensor --lib -- tests::subnet::test_get_subnet_account_id_exists_and_is_distinct_for_257_consecutive_subnets --exact --nocapture +#[test] +fn test_get_subnet_account_id_exists_and_is_distinct_for_257_consecutive_subnets() { + new_test_ext(1).execute_with(|| { + let mut account_ids = BTreeSet::new(); + + for raw_netuid in 0u16..=256u16 { + let netuid = NetUid::from(raw_netuid); + add_network(netuid, 10, 0); + + let account_id = SubtensorModule::get_subnet_account_id(netuid); + assert!( + account_ids.insert(account_id), + "duplicate subnet account id for netuid {:?}", + netuid + ); + } + + assert_eq!(account_ids.len(), 257); + }); +} + +// cargo test --package pallet-subtensor --lib -- tests::subnet::test_is_subnet_account_id --exact --nocapture +#[test] +fn test_is_subnet_account_id() { + new_test_ext(1).execute_with(|| { + for raw_netuid in 0u16..=2048u16 { + let netuid = NetUid::from(raw_netuid); + add_network(netuid, 10, 0); + + let account_id = SubtensorModule::get_subnet_account_id(netuid).unwrap(); + let roudtrip_netuid = SubtensorModule::is_subnet_account_id(&account_id); + assert_eq!(netuid, roudtrip_netuid.unwrap()); + } + + // Not a subnet account + let not_subnet_account_id = U256::from(1); + assert!(SubtensorModule::is_subnet_account_id(¬_subnet_account_id).is_none()); + }); +} + +// cargo test --package pallet-subtensor --lib -- tests::subnet::test_cannot_register_system_hotkey --exact --nocapture +#[test] +fn test_cannot_register_system_hotkey() { + new_test_ext(1).execute_with(|| { + for raw_netuid in 0u16..=2048u16 { + let coldkey = U256::from(1); + let netuid = NetUid::from(raw_netuid); + add_network(netuid, 10, 0); + + let account_id = SubtensorModule::get_subnet_account_id(netuid).unwrap(); + assert_err!( + SubtensorModule::create_account_if_non_existent(&coldkey, &account_id), + Error::::NonAssociatedColdKey + ); + assert!(!SubtensorModule::coldkey_owns_hotkey(&coldkey, &account_id),); + } + }); +} diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index e756429b8d..fd0281ad35 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -48,7 +48,7 @@ fn test_announce_coldkey_swap_works() { assert_eq!(ColdkeySwapAnnouncements::::iter().count(), 0); let swap_cost = SubtensorModule::get_key_swap_cost(); - SubtensorModule::add_balance_to_coldkey_account(&who, swap_cost + ed); + add_balance_to_coldkey_account(&who, swap_cost + ed); assert_eq!(SubtensorModule::get_coldkey_balance(&who), swap_cost + ed); assert_ok!(SubtensorModule::announce_coldkey_swap( @@ -85,7 +85,7 @@ fn test_announce_coldkey_swap_with_existing_announcement_past_delay_works() { assert_eq!(ColdkeySwapAnnouncements::::iter().count(), 0); let swap_cost = SubtensorModule::get_key_swap_cost(); - SubtensorModule::add_balance_to_coldkey_account(&who, swap_cost * 2.into()); + add_balance_to_coldkey_account(&who, swap_cost * 2.into()); assert_ok!(SubtensorModule::announce_coldkey_swap( RuntimeOrigin::signed(who), @@ -126,7 +126,7 @@ fn test_announce_coldkey_swap_only_pays_swap_cost_if_no_announcement_exists() { let ed = ExistentialDeposit::get(); let swap_cost = SubtensorModule::get_key_swap_cost(); - SubtensorModule::add_balance_to_coldkey_account(&who, swap_cost + ed); + add_balance_to_coldkey_account(&who, swap_cost + ed); assert_eq!(SubtensorModule::get_coldkey_balance(&who), swap_cost + ed); assert_ok!(SubtensorModule::announce_coldkey_swap( @@ -179,7 +179,7 @@ fn test_announce_coldkey_swap_with_existing_announcement_not_past_delay_fails() let swap_cost = SubtensorModule::get_key_swap_cost(); let ed = ExistentialDeposit::get(); - SubtensorModule::add_balance_to_coldkey_account(&who, swap_cost + ed); + add_balance_to_coldkey_account(&who, swap_cost + ed); assert_ok!(SubtensorModule::announce_coldkey_swap( RuntimeOrigin::signed(who), @@ -222,7 +222,7 @@ fn test_swap_coldkey_announced_works() { let delay = ColdkeySwapAnnouncementDelay::::get() + 1; run_to_block(now + delay); - SubtensorModule::add_balance_to_coldkey_account(&who, stake1 + stake2 + stake3 + ed); + add_balance_to_coldkey_account(&who, stake1 + stake2 + stake3 + ed); let expected_remaining: u64 = ed.to_u64(); @@ -368,7 +368,7 @@ fn test_swap_coldkey_announced_with_already_associated_coldkey_fails() { let swap_cost = SubtensorModule::get_key_swap_cost(); let ed = ExistentialDeposit::get(); - SubtensorModule::add_balance_to_coldkey_account(&who, swap_cost + ed); + add_balance_to_coldkey_account(&who, swap_cost + ed); assert_ok!(SubtensorModule::announce_coldkey_swap( RuntimeOrigin::signed(who), @@ -435,10 +435,7 @@ fn test_swap_coldkey_works() { let stake3 = min_stake * 30.into(); // Fund: stake_total + (swap_cost + ED). - SubtensorModule::add_balance_to_coldkey_account( - &old_coldkey, - swap_cost + stake1 + stake2 + stake3 + ed, - ); + add_balance_to_coldkey_account(&old_coldkey, swap_cost + stake1 + stake2 + stake3 + ed); // Some old announcement and dispute that will be cleared let now = System::block_number() - 100; @@ -519,10 +516,7 @@ fn test_swap_coldkey_works_with_zero_cost() { let stake2 = min_stake * 20.into(); let stake3 = min_stake * 30.into(); - SubtensorModule::add_balance_to_coldkey_account( - &old_coldkey, - stake1 + stake2 + stake3 + ed, - ); + add_balance_to_coldkey_account(&old_coldkey, stake1 + stake2 + stake3 + ed); let expected_remaining = ed; let ( @@ -607,6 +601,7 @@ fn test_swap_coldkey_with_bad_origin_fails() { }); } +// cargo test --package pallet-subtensor --lib -- tests::swap_coldkey::test_swap_coldkey_with_not_enough_balance_to_pay_swap_cost_fails --exact --nocapture #[test] fn test_swap_coldkey_with_not_enough_balance_to_pay_swap_cost_fails() { new_test_ext(1).execute_with(|| { @@ -627,7 +622,8 @@ fn test_swap_coldkey_with_not_enough_balance_to_pay_swap_cost_fails() { // Needs to preserve ED let balance = SubtensorModule::get_key_swap_cost() + ExistentialDeposit::get() - 1.into(); - SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, balance); + add_balance_to_coldkey_account(&old_coldkey, balance); + assert_noop!( SubtensorModule::swap_coldkey( RuntimeOrigin::root(), @@ -681,7 +677,7 @@ fn test_announce_coldkey_swap_with_not_enough_balance_to_pay_swap_cost_fails() { // Needs to preserve ED let balance = SubtensorModule::get_key_swap_cost() + ExistentialDeposit::get() - 1.into(); - SubtensorModule::add_balance_to_coldkey_account(&who, balance); + add_balance_to_coldkey_account(&who, balance); assert_noop!( SubtensorModule::announce_coldkey_swap(RuntimeOrigin::signed(who), new_coldkey_hash), Error::::NotEnoughBalanceToPaySwapColdKey @@ -720,7 +716,10 @@ fn test_do_swap_coldkey_with_max_values() { let other_coldkey = U256::from(7); let netuid = NetUid::from(1); let netuid2 = NetUid::from(2); - let max_stake = TaoBalance::from(21_000_000_000_000_000_u64); // 21 Million TAO; max possible balance. + // Max possible balance: (21M - EDs - ...) / 2 + let ed = u64::from(ExistentialDeposit::get()); + let locks = 200_000_000_000_u64; + let max_stake = (21_000_000_000_000_000_u64 - 2 * ed - 100) / 2; // Add a network add_network(netuid, 1, 0); @@ -732,19 +731,18 @@ fn test_do_swap_coldkey_with_max_values() { register_ok_neuron(netuid2, hotkey2, other_coldkey, 1001000); // Give balance to old_coldkey and old_coldkey2. - SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, max_stake + 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&old_coldkey2, max_stake + 1_000.into()); + add_balance_to_coldkey_account(&old_coldkey, max_stake.into()); + add_balance_to_coldkey_account(&old_coldkey2, max_stake.into()); - let reserve = u64::from(max_stake) * 10; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - mock::setup_reserves(netuid2, reserve.into(), reserve.into()); + mock::setup_reserves(netuid, max_stake.into(), max_stake.into()); + mock::setup_reserves(netuid2, max_stake.into(), max_stake.into()); // Stake to hotkey on each subnet. assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), hotkey, netuid, - max_stake + max_stake.into() )); let expected_stake1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -756,7 +754,7 @@ fn test_do_swap_coldkey_with_max_values() { <::RuntimeOrigin>::signed(old_coldkey2), hotkey2, netuid2, - max_stake + max_stake.into() )); let expected_stake2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, @@ -807,8 +805,8 @@ fn test_do_swap_coldkey_effect_on_delegated_stake() { StakingHotkeys::::insert(old_coldkey, vec![hotkey]); StakingHotkeys::::insert(delegator, vec![hotkey]); SubtensorModule::create_account_if_non_existent(&old_coldkey, &hotkey); - SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, stake); - SubtensorModule::add_balance_to_coldkey_account(&delegator, stake); + add_balance_to_coldkey_account(&old_coldkey, stake); + add_balance_to_coldkey_account(&delegator, stake); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(old_coldkey), @@ -868,7 +866,7 @@ fn test_swap_delegated_stake_for_coldkey() { // Notice hotkey1 and hotkey2 are Owned by other_coldkey // old_coldkey and new_coldkey therefore delegates stake to them // === Give old_coldkey some balance === - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &old_coldkey, stake_amount1 + stake_amount2 + 1_000_000.into(), ); @@ -1008,13 +1006,13 @@ fn test_coldkey_swap_total() { let stake = DefaultMinStake::::get() * 10.into(); // Initial funding. Burns will reduce these balances. - SubtensorModule::add_balance_to_coldkey_account(&coldkey, stake * 6.into() + ed.into()); - SubtensorModule::add_balance_to_coldkey_account(&delegate1, stake * 2.into() + ed.into()); - SubtensorModule::add_balance_to_coldkey_account(&delegate2, stake * 2.into() + ed.into()); - SubtensorModule::add_balance_to_coldkey_account(&delegate3, stake * 2.into() + ed.into()); - SubtensorModule::add_balance_to_coldkey_account(&nominator1, stake * 2.into() + ed.into()); - SubtensorModule::add_balance_to_coldkey_account(&nominator2, stake * 2.into() + ed.into()); - SubtensorModule::add_balance_to_coldkey_account(&nominator3, stake * 2.into() + ed.into()); + add_balance_to_coldkey_account(&coldkey, stake * 6.into() + ed.into()); + add_balance_to_coldkey_account(&delegate1, stake * 2.into() + ed.into()); + add_balance_to_coldkey_account(&delegate2, stake * 2.into() + ed.into()); + add_balance_to_coldkey_account(&delegate3, stake * 2.into() + ed.into()); + add_balance_to_coldkey_account(&nominator1, stake * 2.into() + ed.into()); + add_balance_to_coldkey_account(&nominator2, stake * 2.into() + ed.into()); + add_balance_to_coldkey_account(&nominator3, stake * 2.into() + ed.into()); let reserve = u64::from(stake) * 10; mock::setup_reserves(netuid1, reserve.into(), reserve.into()); @@ -1044,7 +1042,7 @@ fn test_coldkey_swap_total() { let ensure_min_balance = |account: &U256, required: TaoBalance| { let bal = SubtensorModule::get_coldkey_balance(account); if bal < required { - SubtensorModule::add_balance_to_coldkey_account(account, required - bal); + add_balance_to_coldkey_account(account, required - bal); } }; @@ -1357,7 +1355,7 @@ fn test_do_swap_coldkey_effect_on_delegations() { delegate )); // register on root register_ok_neuron(netuid2, delegate, owner, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, stake * 10.into()); + add_balance_to_coldkey_account(&coldkey, stake * 10.into()); // since the reserves are equal and we stake the same amount to both networks, we can reuse // this values for different networks. but you should take it into account in case of tests @@ -1697,7 +1695,7 @@ macro_rules! comprehensive_setup { let current_free = SubtensorModule::get_coldkey_balance(&$who); if current_free < required_free { - SubtensorModule::add_balance_to_coldkey_account(&$who, required_free - current_free); + add_balance_to_coldkey_account(&$who, required_free - current_free); } // Now staking will succeed and leave exactly expected_remaining behind. @@ -1900,7 +1898,7 @@ fn coldkey_hash_of(coldkey: U256) -> H256 { fn announce_coldkey_swap(who: U256, new_coldkey: U256) { let ed = ExistentialDeposit::get(); let swap_cost = SubtensorModule::get_key_swap_cost(); - SubtensorModule::add_balance_to_coldkey_account(&who, ed + swap_cost); + add_balance_to_coldkey_account(&who, ed + swap_cost); assert_ok!(SubtensorModule::announce_coldkey_swap( RuntimeOrigin::signed(who), diff --git a/pallets/subtensor/src/tests/swap_hotkey.rs b/pallets/subtensor/src/tests/swap_hotkey.rs index 37c63d2c44..f8fe57f8de 100644 --- a/pallets/subtensor/src/tests/swap_hotkey.rs +++ b/pallets/subtensor/src/tests/swap_hotkey.rs @@ -81,7 +81,7 @@ fn test_swap_total_hotkey_stake() { mock::setup_reserves(netuid, reserve.into(), reserve.into()); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount); + add_balance_to_coldkey_account(&coldkey, amount); // Add stake let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, amount); @@ -420,14 +420,8 @@ fn test_swap_hotkey_with_multiple_coldkeys() { StakingHotkeys::::insert(coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(coldkey2, vec![old_hotkey]); SubtensorModule::create_account_if_non_existent(&coldkey1, &old_hotkey); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey1, - stake + ExistentialDeposit::get(), - ); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey2, - stake + ExistentialDeposit::get(), - ); + add_balance_to_coldkey_account(&coldkey1, stake + ExistentialDeposit::get()); + add_balance_to_coldkey_account(&coldkey2, stake + ExistentialDeposit::get()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey1), @@ -519,14 +513,8 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { Alpha::::insert((old_hotkey, coldkey2, netuid), U64F64::from_num(100)); SubtensorModule::create_account_if_non_existent(&coldkey1, &old_hotkey); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey1, - stake + ExistentialDeposit::get(), - ); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey2, - stake + ExistentialDeposit::get(), - ); + add_balance_to_coldkey_account(&coldkey1, stake + ExistentialDeposit::get()); + add_balance_to_coldkey_account(&coldkey2, stake + ExistentialDeposit::get()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey1), old_hotkey, @@ -618,8 +606,8 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { mock::setup_reserves(netuid2, reserve.into(), reserve.into()); // Add balance to both coldkeys - SubtensorModule::add_balance_to_coldkey_account(&coldkey1, stake + 1_000.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey2, stake + 1_000.into()); + add_balance_to_coldkey_account(&coldkey1, stake + 1_000.into()); + add_balance_to_coldkey_account(&coldkey2, stake + 1_000.into()); // Stake with coldkey1 assert_ok!(SubtensorModule::add_stake( @@ -741,7 +729,7 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { let new_hotkey_1 = U256::from(2); let new_hotkey_2 = U256::from(4); let coldkey = U256::from(3); - let swap_cost = TaoBalance::from(1_000_000_000u64 * 2); + let swap_cost = SubtensorModule::get_key_swap_cost() * 2.into(); let tx_rate_limit = 1; @@ -757,7 +745,7 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { // Setup initial state add_network(netuid, tempo, 0); register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); + add_balance_to_coldkey_account(&coldkey, swap_cost + ExistentialDeposit::get()); // Perform the first swap assert_ok!(SubtensorModule::do_swap_hotkey( @@ -807,7 +795,7 @@ fn test_do_swap_hotkey_err_not_owner() { // Setup initial state add_network(netuid, tempo, 0); register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); + add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); // Attempt the swap with a non-owner coldkey assert_err!( @@ -1140,7 +1128,7 @@ fn test_swap_hotkey_error_cases() { ); let initial_balance = SubtensorModule::get_key_swap_cost() + 1000.into(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance); + add_balance_to_coldkey_account(&coldkey, initial_balance); // Test new hotkey same as old assert_noop!( @@ -1518,7 +1506,7 @@ fn test_swap_hotkey_swap_rate_limits() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let last_tx_block = 123; let delegate_take_block = 4567; diff --git a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs index 1d39eb229e..b8fd57863a 100644 --- a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs +++ b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs @@ -24,7 +24,7 @@ fn test_swap_owner() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); Owner::::insert(old_hotkey, coldkey); System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); assert_ok!(SubtensorModule::do_swap_hotkey( @@ -49,7 +49,7 @@ fn test_swap_owned_hotkeys() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); OwnedHotkeys::::insert(coldkey, vec![old_hotkey]); System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); @@ -83,7 +83,7 @@ fn test_swap_total_hotkey_stake() { remove_owner_registration_stake(netuid); // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Add stake assert_ok!(SubtensorModule::add_stake( @@ -138,7 +138,7 @@ fn test_swap_delegates() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); Delegates::::insert(old_hotkey, 100); System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); @@ -164,7 +164,7 @@ fn test_swap_subnet_membership() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); @@ -191,7 +191,7 @@ fn test_swap_uids_and_keys() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); Uids::::insert(netuid, old_hotkey, uid); @@ -224,7 +224,7 @@ fn test_swap_prometheus() { let prometheus_info = PrometheusInfo::default(); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); @@ -258,7 +258,7 @@ fn test_swap_axons() { let axon_info = AxonInfo::default(); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); Axons::::insert(netuid, old_hotkey, axon_info.clone()); @@ -289,7 +289,7 @@ fn test_swap_certificates() { let certificate = NeuronCertificate::try_from(vec![1, 2, 3]).unwrap(); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); NeuronCertificates::::insert(netuid, old_hotkey, certificate.clone()); @@ -326,7 +326,7 @@ fn test_swap_weight_commits() { weight_commits.push_back((H256::from_low_u64_be(100), 200, 1, 1)); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); WeightCommits::::insert( @@ -368,7 +368,7 @@ fn test_swap_loaded_emission() { let validator_emission = 1000u64; let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(old_hotkey, netuid, true); LoadedEmission::::insert( @@ -401,7 +401,7 @@ fn test_swap_staking_hotkeys() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); StakingHotkeys::::insert(coldkey, vec![old_hotkey]); Alpha::::insert((old_hotkey, coldkey, netuid), U64F64::from_num(100)); @@ -439,8 +439,8 @@ fn test_swap_hotkey_with_multiple_coldkeys() { StakingHotkeys::::insert(coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(coldkey2, vec![old_hotkey]); SubtensorModule::create_account_if_non_existent(&coldkey1, &old_hotkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey1, u64::MAX.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey2, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey1, 1_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey2, 1_000_000_000_000_u64.into()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey1), @@ -498,7 +498,7 @@ fn test_swap_hotkey_with_multiple_subnets() { let new_hotkey_2 = U256::from(3); let coldkey = U256::from(4); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let netuid1 = add_dynamic_network(&old_hotkey, &coldkey); let netuid2 = add_dynamic_network(&old_hotkey, &coldkey); @@ -546,8 +546,8 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { let staker5 = U256::from(5); let stake = 1_000_000_000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey1, u64::MAX.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey2, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey1, 1_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey2, 1_000_000_000_000_u64.into()); // Set up initial state StakingHotkeys::::insert(coldkey1, vec![old_hotkey]); @@ -601,7 +601,7 @@ fn test_swap_hotkey_with_no_stake() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Set up initial state with no stake Owner::::insert(old_hotkey, coldkey); @@ -645,8 +645,8 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { register_ok_neuron(netuid2, old_hotkey, coldkey1, 1234); // Add balance to both coldkeys - SubtensorModule::add_balance_to_coldkey_account(&coldkey1, u64::MAX.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey2, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey1, 1_000_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey2, 1_000_000_000_000_u64.into()); // Stake with coldkey1 assert_ok!(SubtensorModule::add_stake( @@ -800,7 +800,7 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { // Setup initial state add_network(netuid, tempo, 0); register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); + add_balance_to_coldkey_account(&coldkey, swap_cost); // Perform the first swap System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); @@ -852,7 +852,7 @@ fn test_do_swap_hotkey_err_not_owner() { // Setup initial state add_network(netuid, tempo, 0); register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); + add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); // Attempt the swap with a non-owner coldkey assert_err!( @@ -877,7 +877,7 @@ fn test_swap_owner_old_hotkey_not_exist() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&new_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Ensure old_hotkey does not exist assert!(!Owner::::contains_key(old_hotkey)); @@ -910,7 +910,7 @@ fn test_swap_owner_new_hotkey_already_exists() { let another_coldkey = U256::from(4); let netuid = add_dynamic_network(&new_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Initialize Owner for old_hotkey and new_hotkey Owner::::insert(old_hotkey, coldkey); @@ -946,7 +946,7 @@ fn test_swap_stake_success() { let subnet_owner_hotkey = U256::from(1002); let netuid = add_dynamic_network(&old_hotkey, &coldkey); remove_owner_registration_stake(netuid); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let amount = 10_000; let shares = U64F64::from_num(10_000); @@ -1033,7 +1033,7 @@ fn test_swap_stake_v2_success() { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let amount = 10_000; let shares = U64F64::from_num(10_000); @@ -1136,7 +1136,7 @@ fn test_swap_hotkey_error_cases() { ); let initial_balance = SubtensorModule::get_key_swap_cost() + 1000.into(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance); + add_balance_to_coldkey_account(&coldkey, initial_balance); // Test new hotkey same as old System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); @@ -1198,7 +1198,7 @@ fn test_swap_child_keys() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let children = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; @@ -1231,7 +1231,7 @@ fn test_swap_child_keys_self_loop() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); let amount = AlphaBalance::from(12345); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Only for checking TotalHotkeyAlpha::::insert(old_hotkey, netuid, AlphaBalance::from(amount)); @@ -1272,7 +1272,7 @@ fn test_swap_parent_keys() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let parents = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; // Initialize ParentKeys for old_hotkey @@ -1319,7 +1319,7 @@ fn test_swap_multiple_subnets() { let netuid1 = add_dynamic_network(&old_hotkey, &coldkey); let netuid2 = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let children1 = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; let children2 = vec![(300u64, U256::from(6))]; @@ -1363,7 +1363,7 @@ fn test_swap_complex_parent_child_structure() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let parent1 = U256::from(4); let parent2 = U256::from(5); let child1 = U256::from(6); @@ -1429,7 +1429,7 @@ fn test_swap_parent_hotkey_childkey_maps() { let parent_new = U256::from(5); let netuid = add_dynamic_network(&parent_old, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); SubtensorModule::create_account_if_non_existent(&coldkey, &parent_old); @@ -1486,7 +1486,7 @@ fn test_swap_child_hotkey_childkey_maps() { let child_old = U256::from(3); let child_new = U256::from(4); let netuid = add_dynamic_network(&child_old, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); SubtensorModule::create_account_if_non_existent(&coldkey, &child_old); SubtensorModule::create_account_if_non_existent(&coldkey, &parent); @@ -1546,7 +1546,7 @@ fn test_swap_hotkey_is_sn_owner_hotkey() { // Create dynamic network let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Check for SubnetOwnerHotkey assert_eq!(SubnetOwnerHotkey::::get(netuid), old_hotkey); @@ -1579,7 +1579,7 @@ fn test_swap_hotkey_swap_rate_limits() { let child_key_take_block = 8910; let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); // Set the last tx block for the old hotkey SubtensorModule::set_last_tx_block(&old_hotkey, last_tx_block); @@ -1622,7 +1622,7 @@ fn test_swap_owner_failed_interval_not_passed() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); Owner::::insert(old_hotkey, coldkey); assert_err!( SubtensorModule::do_swap_hotkey( @@ -1645,7 +1645,7 @@ fn test_swap_owner_check_swap_block_set() { let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); Owner::::insert(old_hotkey, coldkey); let new_block_number = System::block_number() + HotkeySwapOnSubnetInterval::get(); System::set_block_number(new_block_number); @@ -1671,7 +1671,7 @@ fn test_swap_owner_check_swap_record_clean_up() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); Owner::::insert(old_hotkey, coldkey); let new_block_number = System::block_number() + HotkeySwapOnSubnetInterval::get(); System::set_block_number(new_block_number); @@ -1713,7 +1713,7 @@ fn test_revert_hotkey_swap_stake_is_not_lost() { add_network(netuid2, tempo, 0); register_ok_neuron(netuid, hk1, coldkey, 0); register_ok_neuron(netuid2, hk1, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost.into()); + add_balance_to_coldkey_account(&coldkey, swap_cost.into()); let hk1_stake_before_increase = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hk1, &coldkey, netuid); @@ -1808,7 +1808,7 @@ fn test_hotkey_swap_keep_stake() { // Setup add_network(netuid, tempo, 0); register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost.into()); + add_balance_to_coldkey_account(&coldkey, swap_cost.into()); VotingPower::::insert(netuid, old_hotkey, voting_power_value); assert_eq!( @@ -1942,7 +1942,7 @@ fn test_revert_hotkey_swap() { add_network(netuid2, tempo, 0); register_ok_neuron(netuid, old_hotkey, coldkey, 0); register_ok_neuron(netuid2, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost.into()); + add_balance_to_coldkey_account(&coldkey, swap_cost.into()); step_block(20); // Perform the first swap (only on netuid) @@ -1982,7 +1982,7 @@ fn test_revert_hotkey_swap_parent_hotkey_childkey_maps() { let netuid = add_dynamic_network(&hk1, &coldkey); let netuid2 = add_dynamic_network(&hk1, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); SubtensorModule::create_account_if_non_existent(&coldkey, &hk1); mock_set_children(&coldkey, &hk1, netuid, &[(u64::MAX, child)]); @@ -2065,7 +2065,7 @@ fn test_revert_hotkey_swap_uids_and_keys() { let netuid = add_dynamic_network(&hk1, &coldkey); let netuid2 = add_dynamic_network(&hk1, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); IsNetworkMember::::insert(hk1, netuid, true); Uids::::insert(netuid, hk1, uid); @@ -2129,7 +2129,7 @@ fn test_revert_hotkey_swap_auto_stake_destination() { add_network(netuid2, 1, 0); register_ok_neuron(netuid, hk1, coldkey, 0); register_ok_neuron(netuid2, hk1, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); AutoStakeDestinationColdkeys::::insert(hk1, netuid, coldkeys.clone()); AutoStakeDestination::::insert(coldkey, netuid, hk1); @@ -2210,7 +2210,7 @@ fn test_revert_hotkey_swap_subnet_owner() { let netuid = add_dynamic_network(&hk1, &coldkey); let netuid2 = add_dynamic_network(&hk1, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); assert_eq!(SubnetOwnerHotkey::::get(netuid), hk1); @@ -2259,7 +2259,7 @@ fn test_revert_hotkey_swap_dividends() { remove_owner_registration_stake(netuid); let netuid2 = add_dynamic_network(&hk1, &coldkey); remove_owner_registration_stake(netuid2); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into()); let amount = 10_000; let shares = U64F64::from_num(10_000); @@ -2448,7 +2448,7 @@ fn test_revert_claim_root_with_swap_hotkey() { let netuid = add_dynamic_network(&hk1, &owner_coldkey); let netuid2 = add_dynamic_network(&hk1, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&owner_coldkey, 1_000_000_000_000_u64.into()); SubtensorModule::set_tao_weight(u64::MAX); let root_stake = 2_000_000u64; @@ -2569,9 +2569,9 @@ fn test_swap_hotkey_with_existing_stake() { register_ok_neuron(netuid, new_hotkey, coldkey, 1234); // Add balance to coldkeys - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 10_000_000_000_u64.into()); - SubtensorModule::add_balance_to_coldkey_account(&staker1, 10_000_000_000_u64.into()); - SubtensorModule::add_balance_to_coldkey_account(&staker2, 10_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 10_000_000_000_u64.into()); + add_balance_to_coldkey_account(&staker1, 10_000_000_000_u64.into()); + add_balance_to_coldkey_account(&staker2, 10_000_000_000_u64.into()); // Stake with staker1 coldkey on old_hotkey assert_ok!(SubtensorModule::add_stake( @@ -2741,9 +2741,9 @@ fn test_revert_hotkey_swap_with_revert_stake_the_same() { register_ok_neuron(netuid_1, hk1, coldkey, 0); register_ok_neuron(netuid_2, hk1, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance.into()); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_4, initial_balance.into()); - SubtensorModule::add_balance_to_coldkey_account(&random_coldkey, initial_balance.into()); + add_balance_to_coldkey_account(&coldkey, initial_balance.into()); + add_balance_to_coldkey_account(&coldkey_4, initial_balance.into()); + add_balance_to_coldkey_account(&random_coldkey, initial_balance.into()); step_block(20); // Waiting interval to be able to swap later // Checking stake for hk1 on both networks @@ -2927,7 +2927,7 @@ fn test_swap_hotkey_root_claims_unchanged_if_not_root() { let netuid = add_dynamic_network(&neuron_hotkey, &owner_coldkey); let new_hotkey = U256::from(10030); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000_000u64; @@ -3013,7 +3013,7 @@ fn test_swap_hotkey_root_claims_changed_if_root() { // Use neuron_hotkey as subnet creator so it receives root dividends let netuid_1 = add_dynamic_network(&neuron_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000_000u64; @@ -3102,7 +3102,7 @@ fn test_swap_hotkey_root_claims_changed_if_all_subnets() { // Use neuron_hotkey as subnet creator so it receives root dividends let netuid_1 = add_dynamic_network(&neuron_hotkey, &owner_coldkey); - SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); + add_balance_to_coldkey_account(&owner_coldkey, u64::MAX.into()); SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 let root_stake = 2_000_000_000u64; diff --git a/pallets/subtensor/src/tests/tao.rs b/pallets/subtensor/src/tests/tao.rs new file mode 100644 index 0000000000..b79b80e3f3 --- /dev/null +++ b/pallets/subtensor/src/tests/tao.rs @@ -0,0 +1,516 @@ +#![allow( + unused, + clippy::indexing_slicing, + clippy::panic, + clippy::unwrap_used, + clippy::expect_used +)] + +use super::mock_high_ed::*; +use crate::tests::mock_high_ed; +use crate::*; +use frame_support::{ + assert_noop, assert_ok, + traits::{ + Imbalance, + tokens::{Fortitude, Preservation, fungible::Inspect as _}, + }, +}; +use sp_core::U256; +use sp_runtime::traits::{AccountIdConversion, Zero}; +use subtensor_runtime_common::TaoBalance; + +const MAX_TAO_ISSUANCE: u64 = 21_000_000_000_000_000_u64; + +/// Helper: balances-pallet total issuance. +fn balances_total_issuance() -> TaoBalance { + ::Currency::total_issuance() +} + +/// Helper: subtensor-pallet total issuance. +fn subtensor_total_issuance() -> TaoBalance { + TotalIssuance::::get() +} + +/// Helper: free/reducible balance view used by tao.rs. +fn reducible_balance(account: &U256) -> TaoBalance { + SubtensorModule::get_coldkey_balance(account) +} + +/// Helper: total balance as seen by the currency implementation. +fn total_balance(account: &U256) -> TaoBalance { + Balances::total_balance(account) +} + +// ---------------------------------------------------- +// transfer_tao +// ---------------------------------------------------- + +#[test] +fn test_transfer_tao_normal_case() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let amount = TaoBalance::from(200); + add_balance_to_coldkey_account(&origin, ExistentialDeposit::get() * 10.into() + amount); + let origin_before = total_balance(&origin); + let dest_before = total_balance(&dest); + + assert!(origin_before >= amount); + + assert_ok!(SubtensorModule::transfer_tao(&origin, &dest, amount)); + + assert_eq!(total_balance(&origin), origin_before - amount); + assert_eq!(total_balance(&dest), dest_before + amount); + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +#[test] +fn test_transfer_tao_zero_balance_zero_amount() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(10_001); + let dest = U256::from(10_002); + + assert_eq!(total_balance(&origin), 0.into()); + assert_eq!(total_balance(&dest), 0.into()); + + assert_ok!(SubtensorModule::transfer_tao(&origin, &dest, 0.into())); + + assert_eq!(total_balance(&origin), 0.into()); + assert_eq!(total_balance(&dest), 0.into()); + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +#[test] +fn test_transfer_tao_zero_balance_non_zero_amount_fails() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(10_011); + let dest = U256::from(10_012); + + assert_eq!(total_balance(&origin), 0.into()); + + assert_noop!( + SubtensorModule::transfer_tao(&origin, &dest, 1u64.into()), + Error::::InsufficientBalance + ); + + assert_eq!(total_balance(&origin), 0.into()); + assert_eq!(total_balance(&dest), 0.into()); + }); +} + +#[test] +fn test_transfer_tao_amount_greater_than_transferrable_fails() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let max_transferrable = reducible_balance(&origin); + let amount = max_transferrable + 1.into(); + + assert_noop!( + SubtensorModule::transfer_tao(&origin, &dest, amount.into()), + Error::::InsufficientBalance + ); + }); +} + +#[test] +fn test_transfer_tao_transfer_exactly_transferrable_succeeds() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let amount = reducible_balance(&origin); + let origin_before = total_balance(&origin); + let dest_before = total_balance(&dest); + + assert_ok!(SubtensorModule::transfer_tao(&origin, &dest, amount.into())); + + assert_eq!(total_balance(&origin), origin_before - amount); + assert_eq!(total_balance(&dest), dest_before + amount); + }); +} + +#[test] +fn test_transfer_tao_can_reap_origin_when_amount_brings_it_below_ed() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let ed = ExistentialDeposit::get(); + let amount = TaoBalance::from(100); + let balance_origin = amount + ed - 1.into(); + let balance_dest = ed + 1234.into(); + add_balance_to_coldkey_account(&origin, balance_origin); + add_balance_to_coldkey_account(&dest, balance_dest); + + assert_ok!(SubtensorModule::transfer_tao(&origin, &dest, amount)); + + // With Preservation::Expendable, origin may be reaped. + assert!(total_balance(&origin).is_zero()); + assert_eq!(total_balance(&dest), amount + balance_dest); + + // Issuance should not change on plain transfer. + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +#[test] +fn test_transfer_tao_to_self_is_ok_and_no_net_balance_change() { + new_test_ext(1).execute_with(|| { + let who = U256::from(1); + let before = total_balance(&who); + let amount = reducible_balance(&who).min(10.into()); + + assert_ok!(SubtensorModule::transfer_tao(&who, &who, amount)); + + assert_eq!(total_balance(&who), before); + }); +} + +// ---------------------------------------------------- +// transfer_all_tao_and_kill +// ---------------------------------------------------- + +#[test] +fn test_transfer_all_tao_and_kill_normal_case() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let ed = ExistentialDeposit::get(); + let amount = TaoBalance::from(100); + let balance_origin = amount + ed; + add_balance_to_coldkey_account(&origin, balance_origin); + + let transferable = reducible_balance(&origin); + let origin_before = total_balance(&origin); + let dest_before = total_balance(&dest); + + assert!(!transferable.is_zero()); + + assert_ok!(SubtensorModule::transfer_all_tao_and_kill(&origin, &dest)); + + assert_eq!(total_balance(&dest), dest_before + transferable); + assert_eq!( + total_balance(&origin), + origin_before.saturating_sub(transferable) + ); + assert_eq!(reducible_balance(&origin), 0.into()); + }); +} + +#[test] +fn test_transfer_all_tao_and_kill_non_existing_origin_is_noop() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(20_001); + let dest = U256::from(20_002); + + assert_eq!(total_balance(&origin), 0.into()); + assert_eq!(reducible_balance(&origin), 0.into()); + + let dest_before = total_balance(&dest); + + assert_ok!(SubtensorModule::transfer_all_tao_and_kill(&origin, &dest)); + + assert_eq!(total_balance(&origin), 0.into()); + assert_eq!(total_balance(&dest), dest_before); + }); +} + +#[test] +fn test_transfer_all_tao_and_kill_preexisting_destination() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let amount_o = TaoBalance::from(200) + ExistentialDeposit::get(); + let amount_d = TaoBalance::from(1000) + ExistentialDeposit::get(); + add_balance_to_coldkey_account(&origin, amount_o); + add_balance_to_coldkey_account(&dest, amount_d); + + let transferable = reducible_balance(&origin); + let dest_before = total_balance(&dest); + + assert!(dest_before > 0.into()); + + assert_ok!(SubtensorModule::transfer_all_tao_and_kill(&origin, &dest)); + + assert_eq!(total_balance(&dest), dest_before + transferable); + assert_eq!(reducible_balance(&origin), 0.into()); + }); +} + +#[test] +fn test_transfer_all_tao_and_kill_to_self_is_noop() { + new_test_ext(1).execute_with(|| { + let who = U256::from(1); + let before_total = total_balance(&who); + let before_reducible = reducible_balance(&who); + + assert_ok!(SubtensorModule::transfer_all_tao_and_kill(&who, &who)); + + assert_eq!(total_balance(&who), before_total); + assert_eq!(reducible_balance(&who), before_reducible); + }); +} + +// ---------------------------------------------------- +// burn_tao +// ---------------------------------------------------- + +#[test] +fn test_burn_tao_increases_burn_address_balance() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let burn_address: U256 = ::BurnAccountId::get().into_account_truncating(); + + let amount = reducible_balance(&coldkey).min(10.into()); + let burn_before = total_balance(&burn_address); + let coldkey_before = total_balance(&coldkey); + + assert_ok!(SubtensorModule::burn_tao(&coldkey, amount)); + + assert_eq!(total_balance(&burn_address), burn_before + amount); + assert_eq!(total_balance(&coldkey), coldkey_before - amount); + + // burn_tao is just a transfer to burn address, not issuance reduction. + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +#[test] +fn test_burn_tao_zero_amount_is_ok() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let burn_address: U256 = ::BurnAccountId::get().into_account_truncating(); + + let burn_before = total_balance(&burn_address); + let coldkey_before = total_balance(&coldkey); + + assert_ok!(SubtensorModule::burn_tao(&coldkey, 0u64.into())); + + assert_eq!(total_balance(&burn_address), burn_before); + assert_eq!(total_balance(&coldkey), coldkey_before); + }); +} + +#[test] +fn test_burn_tao_insufficient_balance_fails() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(30_001); + + assert_noop!( + SubtensorModule::burn_tao(&coldkey, 1u64.into()), + Error::::InsufficientBalance + ); + }); +} + +// ---------------------------------------------------- +// recycle_tao / issuance consistency +// ---------------------------------------------------- + +#[test] +fn test_recycle_tao_reduces_both_balances_and_subtensor_total_issuance() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let max_preserving = SubtensorModule::get_coldkey_balance(&coldkey); + let amount = max_preserving.min(10.into()); + + let coldkey_before = total_balance(&coldkey); + let balances_ti_before = balances_total_issuance(); + let subtensor_ti_before = subtensor_total_issuance(); + + assert_ok!(SubtensorModule::recycle_tao(&coldkey, amount)); + + assert_eq!(total_balance(&coldkey), coldkey_before - amount); + + // Balances-pallet withdraw burns supply. + assert_eq!(balances_total_issuance(), balances_ti_before - amount); + + // Subtensor TI is reduced explicitly in recycle_tao. + assert_eq!(subtensor_total_issuance(), subtensor_ti_before - amount); + + // End state still aligned. + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +#[test] +fn test_recycle_tao_amount_greater_than_max_preserving_fails() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let max_preserving: u64 = ::Currency::reducible_balance( + &coldkey, + frame_support::traits::tokens::Preservation::Preserve, + frame_support::traits::tokens::Fortitude::Polite, + ) + .into(); + + let too_much = max_preserving.saturating_add(1); + + assert_noop!( + SubtensorModule::recycle_tao(&coldkey, too_much.into()), + Error::::InsufficientBalance + ); + + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +#[test] +fn test_recycle_tao_zero_amount_keeps_issuance_equal() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let balances_before = balances_total_issuance(); + let subtensor_before = subtensor_total_issuance(); + let balance_before = total_balance(&coldkey); + + assert_ok!(SubtensorModule::recycle_tao(&coldkey, 0u64.into())); + + assert_eq!(total_balance(&coldkey), balance_before); + assert_eq!(balances_total_issuance(), balances_before); + assert_eq!(subtensor_total_issuance(), subtensor_before); + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +/// This is the invariant you asked for in normal ED=1 test runtime: +/// plain transfers and burns should keep both issuance trackers aligned, +/// and recycle should reduce both by the same amount. +#[test] +fn test_total_issuance_subtensor_matches_balances_across_tao_operations() { + new_test_ext(1).execute_with(|| { + let a = U256::from(1); + let b = U256::from(2); + + let ed = ExistentialDeposit::get(); + let balance = TaoBalance::from(1_000_000) + ed - 1.into(); + add_balance_to_coldkey_account(&a, balance); + add_balance_to_coldkey_account(&b, balance); + + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + + assert_ok!(SubtensorModule::transfer_tao(&a, &b, 1000.into())); + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + + assert_ok!(SubtensorModule::burn_tao(&a, 1000.into())); + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + + let max_preserving: u64 = ::Currency::reducible_balance( + &a, + frame_support::traits::tokens::Preservation::Preserve, + frame_support::traits::tokens::Fortitude::Polite, + ) + .into(); + let recycle_amount = max_preserving.min(1); + assert_ok!(SubtensorModule::recycle_tao(&a, recycle_amount.into())); + assert_eq!(balances_total_issuance(), subtensor_total_issuance()); + }); +} + +// ---------------------------------------------------- +// mint_tao +// ---------------------------------------------------- + +/// This is expected to fail with the current implementation: +/// mint_tao issues into the balances pallet but does not update +/// SubtensorModule::TotalIssuance. +#[test] +fn test_mint_tao_increases_total_issuance_in_balances_and_subtensor() { + new_test_ext(1).execute_with(|| { + let amount = TaoBalance::from(123); + + let balances_before = balances_total_issuance(); + let subtensor_before = subtensor_total_issuance(); + + let credit = SubtensorModule::mint_tao(amount); + + assert_eq!(credit.peek(), amount); + + // This one should pass. + assert_eq!(balances_total_issuance(), balances_before + amount); + + // This one is expected to fail until mint_tao updates TotalIssuance::. + assert_eq!(subtensor_total_issuance(), subtensor_before + amount); + }); +} + +#[test] +fn test_mint_tao_zero_amount() { + new_test_ext(1).execute_with(|| { + let balances_before = balances_total_issuance(); + let subtensor_before = subtensor_total_issuance(); + + let credit = SubtensorModule::mint_tao(0u64.into()); + + assert_eq!(u64::from(credit.peek()), 0); + assert_eq!(balances_total_issuance(), balances_before); + assert_eq!(subtensor_total_issuance(), subtensor_before); + }); +} + +#[test] +fn test_mint_tao_respects_max_issuance_cap_in_balances() { + new_test_ext(1).execute_with(|| { + // We cannot directly force balances-pallet issuance above the cap in every mock, + // but we *can* set subtensor's mirror and still verify that mint_tao uses the + // balances-pallet total issuance as its source of truth. + // + // This test is mostly a guard that the returned credit is capped by + // MAX_TAO_ISSUANCE - Currency::total_issuance(). + let balances_before = balances_total_issuance(); + let remaining = TaoBalance::from(MAX_TAO_ISSUANCE) - balances_before; + let request = remaining + 1000.into(); + + let credit = SubtensorModule::mint_tao(request.into()); + + assert_eq!(credit.peek(), remaining); + assert_eq!(balances_total_issuance(), MAX_TAO_ISSUANCE.into()); + }); +} + +#[test] +fn test_transfer_tao_reaps_origin() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + let dest = U256::from(2); + + let ed = ExistentialDeposit::get(); + let balance_origin = TaoBalance::from(3) + ed; + let amount = TaoBalance::from(2) + ed; + add_balance_to_coldkey_account(&origin, balance_origin); + let subtensor_ti_before = subtensor_total_issuance(); + let balances_ti_before = balances_total_issuance(); + + assert_ok!(SubtensorModule::transfer_tao(&origin, &dest, amount)); + + let subtensor_ti_after = subtensor_total_issuance(); + let balances_ti_after = balances_total_issuance(); + + assert_eq!(Balances::total_balance(&origin), 0.into()); + assert_eq!(Balances::total_balance(&dest), amount); + assert_eq!(balances_ti_before - balances_ti_after, 1.into()); + assert_eq!(subtensor_ti_before - subtensor_ti_after, 1.into()); + }); +} + +#[test] +fn test_recycle_tao_cannot_cross_preserve_threshold_in_high_ed_runtime() { + new_test_ext(1).execute_with(|| { + let origin = U256::from(1); + + let max_preserving = + Balances::reducible_balance(&origin, Preservation::Preserve, Fortitude::Polite); + + assert_noop!( + SubtensorModule::recycle_tao(&origin, max_preserving + 1u64.into()), + Error::::InsufficientBalance + ); + }); +} diff --git a/pallets/subtensor/src/tests/voting_power.rs b/pallets/subtensor/src/tests/voting_power.rs index 3ffb1a6611..9af3639b99 100644 --- a/pallets/subtensor/src/tests/voting_power.rs +++ b/pallets/subtensor/src/tests/voting_power.rs @@ -77,7 +77,7 @@ impl VotingPowerTestFixture { #[allow(clippy::arithmetic_side_effects)] fn setup_for_staking_with_amount(&self, amount: u64) { mock::setup_reserves(self.netuid, (amount * 100).into(), (amount * 100).into()); - SubtensorModule::add_balance_to_coldkey_account(&self.coldkey, (amount * 10).into()); + add_balance_to_coldkey_account(&self.coldkey, (amount * 10).into()); } /// Enable voting power tracking for the subnet @@ -401,10 +401,7 @@ fn test_only_validators_get_voting_power() { (DEFAULT_STAKE_AMOUNT * 100).into(), (DEFAULT_STAKE_AMOUNT * 100).into(), ); - SubtensorModule::add_balance_to_coldkey_account( - &coldkey, - (DEFAULT_STAKE_AMOUNT * 20).into(), - ); + add_balance_to_coldkey_account(&coldkey, (DEFAULT_STAKE_AMOUNT * 20).into()); // Register miner register_ok_neuron(netuid, miner_hotkey, coldkey, 0); diff --git a/pallets/subtensor/src/tests/weights.rs b/pallets/subtensor/src/tests/weights.rs index 5237cca131..36cf17bfd8 100644 --- a/pallets/subtensor/src/tests/weights.rs +++ b/pallets/subtensor/src/tests/weights.rs @@ -119,7 +119,7 @@ fn test_commit_weights_validate() { SubtensorModule::append_neuron(netuid, &hotkey, 0); crate::Owner::::insert(hotkey, coldkey); - SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); + add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); let min_stake = 500_000_000_000_u64; let reserve = min_stake * 1000; @@ -255,7 +255,7 @@ fn test_set_weights_validate() { SubtensorModule::append_neuron(netuid, &hotkey, 0); crate::Owner::::insert(hotkey, coldkey); - SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); + add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); let min_stake = TaoBalance::from(500_000_000_000_u64); @@ -361,7 +361,7 @@ fn test_reveal_weights_validate() { SubtensorModule::append_neuron(netuid, &hotkey2, 0); crate::Owner::::insert(hotkey, coldkey); crate::Owner::::insert(hotkey2, coldkey); - SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); + add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); let min_stake = TaoBalance::from(500_000_000_000_u64); // Set the minimum stake @@ -544,7 +544,7 @@ fn test_batch_reveal_weights_validate() { SubtensorModule::append_neuron(netuid, &hotkey2, 0); crate::Owner::::insert(hotkey, coldkey); crate::Owner::::insert(hotkey2, coldkey); - SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); + add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); let min_stake = TaoBalance::from(500_000_000_000_u64); @@ -782,7 +782,7 @@ fn test_set_stake_threshold_failed() { add_network_disable_commit_reveal(netuid, 1, 0); register_ok_neuron(netuid, hotkey, coldkey, 2143124); SubtensorModule::set_stake_threshold(20_000_000_000_000); - SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); + add_balance_to_coldkey_account(&hotkey, u64::MAX.into()); // Check the signed extension function. assert_eq!(SubtensorModule::get_stake_threshold(), 20_000_000_000_000); @@ -928,7 +928,7 @@ fn test_weights_err_setting_weights_too_fast() { SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id) .expect("Not registered."); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(66), 1.into()); + add_balance_to_coldkey_account(&U256::from(66), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &(U256::from(66)), @@ -1021,7 +1021,7 @@ fn test_weights_err_has_duplicate_ids() { SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id) .expect("Not registered."); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(77), 1.into()); + add_balance_to_coldkey_account(&U256::from(77), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &(U256::from(77)), @@ -1124,7 +1124,7 @@ fn test_set_weights_err_invalid_uid() { .expect("Not registered."); SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(66), 1.into()); + add_balance_to_coldkey_account(&U256::from(66), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &(U256::from(66)), @@ -1160,7 +1160,7 @@ fn test_set_weight_not_enough_values() { let neuron_uid: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &U256::from(1)) .expect("Not registered."); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(2), 1.into()); + add_balance_to_coldkey_account(&U256::from(2), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &account_id, &(U256::from(2)), @@ -1268,7 +1268,7 @@ fn test_set_weights_sum_larger_than_u16_max() { .expect("Not registered."); SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(2), 1.into()); + add_balance_to_coldkey_account(&U256::from(2), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(2)), @@ -1731,8 +1731,8 @@ fn test_commit_reveal_weights_ok() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -1799,8 +1799,8 @@ fn test_commit_reveal_tempo_interval() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -1934,8 +1934,8 @@ fn test_commit_reveal_hash() { SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -2034,8 +2034,8 @@ fn test_commit_reveal_disabled_or_enabled() { SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -2111,8 +2111,8 @@ fn test_toggle_commit_reveal_weights_and_set_weights() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_weights_set_rate_limit(netuid, 5); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -2197,8 +2197,8 @@ fn test_tempo_change_during_commit_reveal_process() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -2346,8 +2346,8 @@ fn test_commit_reveal_multiple_commits() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -2752,8 +2752,8 @@ fn test_expired_commits_handling_in_commit_and_reveal() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -2951,8 +2951,8 @@ fn test_reveal_at_exact_epoch() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -3115,8 +3115,8 @@ fn test_tempo_and_reveal_period_change_during_commit_reveal_process() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -3302,8 +3302,8 @@ fn test_commit_reveal_order_enforcement() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -3561,8 +3561,8 @@ fn test_successful_batch_reveal() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -3639,8 +3639,8 @@ fn test_batch_reveal_with_expired_commits() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -4056,8 +4056,8 @@ fn test_batch_reveal_with_out_of_order_commits() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -4457,8 +4457,8 @@ fn test_get_reveal_blocks() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -4591,8 +4591,8 @@ fn test_commit_weights_rate_limit() { SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1.into()); + add_balance_to_coldkey_account(&U256::from(0), 1.into()); + add_balance_to_coldkey_account(&U256::from(1), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(0)), &(U256::from(0)), @@ -4779,8 +4779,8 @@ fn test_reveal_crv3_commits_success() { SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid1, true); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid2, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(3), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(4), 1.into()); + add_balance_to_coldkey_account(&U256::from(3), 1.into()); + add_balance_to_coldkey_account(&U256::from(4), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &(U256::from(3)), @@ -6038,7 +6038,7 @@ fn test_reveal_crv3_commits_multiple_valid_commits_all_processed() { SubtensorModule::set_validator_permit_for_uid(netuid, i as u16, true); // add minimal stake so `do_set_weights` will succeed - SubtensorModule::add_balance_to_coldkey_account(&cold, 1.into()); + add_balance_to_coldkey_account(&cold, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( hk, &cold, @@ -6136,7 +6136,7 @@ fn test_reveal_crv3_commits_max_neurons() { SubtensorModule::set_validator_permit_for_uid(netuid, i, true); // give each neuron a nominal stake (safe even if not needed) - SubtensorModule::add_balance_to_coldkey_account(&cold, 1.into()); + add_balance_to_coldkey_account(&cold, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hk, &cold, @@ -6358,8 +6358,8 @@ fn test_reveal_crv3_commits_hotkey_check() { SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid1, true); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid2, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(3), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(4), 1.into()); + add_balance_to_coldkey_account(&U256::from(3), 1.into()); + add_balance_to_coldkey_account(&U256::from(4), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &(U256::from(3)), @@ -6475,8 +6475,8 @@ fn test_reveal_crv3_commits_hotkey_check() { SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid1, true); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid2, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(3), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(4), 1.into()); + add_balance_to_coldkey_account(&U256::from(3), 1.into()); + add_balance_to_coldkey_account(&U256::from(4), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &(U256::from(3)), @@ -6741,8 +6741,8 @@ fn test_reveal_crv3_commits_legacy_payload_success() { SubtensorModule::set_validator_permit_for_uid(netuid, uid1, true); SubtensorModule::set_validator_permit_for_uid(netuid, uid2, true); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(3), 1.into()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(4), 1.into()); + add_balance_to_coldkey_account(&U256::from(3), 1.into()); + add_balance_to_coldkey_account(&U256::from(4), 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &U256::from(3), @@ -6874,7 +6874,7 @@ fn test_subnet_owner_can_validate_without_stake_or_manual_permit() { // Add one non-owner neuron with deterministic subnet stake. register_ok_neuron(netuid, other_hotkey, other_coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&other_coldkey, 1.into()); + add_balance_to_coldkey_account(&other_coldkey, 1.into()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &other_hotkey, &other_coldkey, diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 6a23e4b5c3..829a68061a 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -337,9 +337,6 @@ impl Pallet { // ======================== // === Token Management === // ======================== - pub fn recycle_tao(amount: TaoBalance) { - TotalIssuance::::put(TotalIssuance::::get().saturating_sub(amount)); - } pub fn increase_issuance(amount: TaoBalance) { TotalIssuance::::put(TotalIssuance::::get().saturating_add(amount)); } @@ -844,9 +841,16 @@ impl Pallet { /// /// * Update the SubnetOwnerHotkey storage. /// * Emits a SubnetOwnerHotkeySet event. - pub fn set_subnet_owner_hotkey(netuid: NetUid, hotkey: &T::AccountId) { + pub fn set_subnet_owner_hotkey(netuid: NetUid, hotkey: &T::AccountId) -> DispatchResult { + // Ensure that hotkey is not a special account + ensure!( + Self::is_subnet_account_id(hotkey).is_none(), + Error::::NonAssociatedColdKey + ); + SubnetOwnerHotkey::::insert(netuid, hotkey.clone()); Self::deposit_event(Event::SubnetOwnerHotkeySet(netuid, hotkey.clone())); + Ok(()) } // Get the uid of the Owner Hotkey for a subnet. diff --git a/pallets/swap/src/mock.rs b/pallets/swap/src/mock.rs index 6df0c3584f..65dcc676a2 100644 --- a/pallets/swap/src/mock.rs +++ b/pallets/swap/src/mock.rs @@ -267,15 +267,6 @@ impl BalanceOps for MockBalanceOps { .into() } - fn increase_balance(_coldkey: &AccountId, _tao: TaoBalance) {} - - fn decrease_balance( - _coldkey: &AccountId, - tao: TaoBalance, - ) -> Result { - Ok(tao) - } - fn increase_stake( _coldkey: &AccountId, _hotkey: &AccountId, diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs index 4386eae4bb..d5a75a9d4d 100644 --- a/pallets/swap/src/pallet/impls.rs +++ b/pallets/swap/src/pallet/impls.rs @@ -5,7 +5,7 @@ use frame_support::storage::{TransactionOutcome, transactional}; use frame_support::{ensure, pallet_prelude::DispatchError, traits::Get, weights::Weight}; use safe_math::*; use sp_arithmetic::{helpers_128bit, traits::Zero}; -use sp_runtime::{DispatchResult, Vec, traits::AccountIdConversion}; +use sp_runtime::{DispatchResult, traits::AccountIdConversion}; use substrate_fixed::types::{I64F64, U64F64, U96F32}; use subtensor_runtime_common::{ AlphaBalance, BalanceOps, NetUid, SubnetInfo, TaoBalance, Token, TokenReserve, @@ -829,131 +829,133 @@ impl Pallet { } /// Dissolve all LPs and clean state. - pub fn do_dissolve_all_liquidity_providers(netuid: NetUid) -> DispatchResultWithPostInfo { - let mut weight = Weight::default(); - if SwapV3Initialized::::get(netuid) { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - // 1) Snapshot only *non‑protocol* positions: (owner, position_id). - struct CloseItem { - owner: A, - pos_id: PositionId, - } - let protocol_account = Self::protocol_account_id(); - weight.saturating_accrue(T::DbWeight::get().reads(1)); - - let mut to_close: sp_std::vec::Vec> = sp_std::vec::Vec::new(); - for ((owner, pos_id), _pos) in Positions::::iter_prefix((netuid,)) { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if owner != protocol_account { - to_close.push(CloseItem { owner, pos_id }); - } - } - - if to_close.is_empty() { - log::debug!( - "dissolve_all_lp: no user positions; netuid={netuid:?}, protocol liquidity untouched" - ); - return Ok(Some(weight).into()); - } - - let mut user_refunded_tao = TaoBalance::ZERO; - let mut user_staked_alpha = AlphaBalance::ZERO; - - let trust: Vec = T::SubnetInfo::get_validator_trust(netuid.into()); - weight.saturating_accrue(T::DbWeight::get().reads(1)); - let permit: Vec = T::SubnetInfo::get_validator_permit(netuid.into()); - weight.saturating_accrue(T::DbWeight::get().reads(1)); - - // Helper: pick target validator uid, only among permitted validators, by highest trust. - let pick_target_uid = |trust: &Vec, permit: &Vec| -> Option { - let mut best_uid: Option = None; - let mut best_trust: u16 = 0; - for (i, (&t, &p)) in trust.iter().zip(permit.iter()).enumerate() { - if p && (best_uid.is_none() || t > best_trust) { - best_uid = Some(i); - best_trust = t; - } - } - best_uid.map(|i| i as u16) - }; - - for CloseItem { owner, pos_id } in to_close.into_iter() { - match Self::do_remove_liquidity(netuid, &owner, pos_id) { - Ok(rm) => { - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 6)); - // α withdrawn from the pool = principal + accrued fees - let alpha_total_from_pool: AlphaBalance = - rm.alpha.saturating_add(rm.fee_alpha); - - // ---------------- USER: refund τ and convert α → stake ---------------- - - // 1) Refund τ principal directly. - let tao_total_from_pool: TaoBalance = rm.tao.saturating_add(rm.fee_tao); - if tao_total_from_pool > TaoBalance::ZERO { - T::BalanceOps::increase_balance(&owner, tao_total_from_pool); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - user_refunded_tao = - user_refunded_tao.saturating_add(tao_total_from_pool); - T::TaoReserve::decrease_provided(netuid, tao_total_from_pool); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } - - // 2) Stake ALL withdrawn α (principal + fees) to the best permitted validator. - if alpha_total_from_pool > AlphaBalance::ZERO { - if let Some(target_uid) = pick_target_uid(&trust, &permit) { - let validator_hotkey: T::AccountId = - T::SubnetInfo::hotkey_of_uid(netuid.into(), target_uid).ok_or( - sp_runtime::DispatchError::Other( - "validator_hotkey_missing", - ), - )?; - weight.saturating_accrue(T::DbWeight::get().reads(1)); - - // Stake α from LP owner (coldkey) to chosen validator (hotkey). - T::BalanceOps::increase_stake( - &owner, - &validator_hotkey, - netuid, - alpha_total_from_pool, - )?; - weight.saturating_accrue(T::DbWeight::get().writes(1)); - user_staked_alpha = - user_staked_alpha.saturating_add(alpha_total_from_pool); - - log::debug!( - "dissolve_all_lp: user dissolved & staked α: netuid={netuid:?}, owner={owner:?}, pos_id={pos_id:?}, α_staked={alpha_total_from_pool:?}, target_uid={target_uid}" - ); - } else { - // No permitted validators; burn to avoid balance drift. - log::debug!( - "dissolve_all_lp: no permitted validators; α burned: netuid={netuid:?}, owner={owner:?}, pos_id={pos_id:?}, α_total={alpha_total_from_pool:?}" - ); - } - - T::AlphaReserve::decrease_provided(netuid, alpha_total_from_pool); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } - } - Err(e) => { - log::debug!( - "dissolve_all_lp: force-close failed: netuid={netuid:?}, owner={owner:?}, pos_id={pos_id:?}, err={e:?}" - ); - weight.saturating_accrue(T::DbWeight::get().reads(1)); - continue; - } - } - } - - log::debug!( - "dissolve_all_liquidity_providers (users-only): netuid={netuid:?}, users_refunded_total_τ={user_refunded_tao:?}, users_staked_total_α={user_staked_alpha:?}; protocol liquidity untouched" - ); - - return Ok(Some(weight).into()); - } - - log::debug!( - "dissolve_all_liquidity_providers: netuid={netuid:?}, mode=V2-or-nonV3, leaving all liquidity/state intact" - ); + pub fn do_dissolve_all_liquidity_providers(_netuid: NetUid) -> DispatchResultWithPostInfo { + // Deprecated in balancer anyway + let weight = Weight::default(); + + // if SwapV3Initialized::::get(netuid) { + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + // // 1) Snapshot only *non‑protocol* positions: (owner, position_id). + // struct CloseItem { + // owner: A, + // pos_id: PositionId, + // } + // let protocol_account = Self::protocol_account_id(); + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + + // let mut to_close: sp_std::vec::Vec> = sp_std::vec::Vec::new(); + // for ((owner, pos_id), _pos) in Positions::::iter_prefix((netuid,)) { + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + // if owner != protocol_account { + // to_close.push(CloseItem { owner, pos_id }); + // } + // } + + // if to_close.is_empty() { + // log::debug!( + // "dissolve_all_lp: no user positions; netuid={netuid:?}, protocol liquidity untouched" + // ); + // return Ok(Some(weight).into()); + // } + + // let mut user_refunded_tao = TaoBalance::ZERO; + // let mut user_staked_alpha = AlphaBalance::ZERO; + + // let trust: Vec = T::SubnetInfo::get_validator_trust(netuid.into()); + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + // let permit: Vec = T::SubnetInfo::get_validator_permit(netuid.into()); + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + + // // Helper: pick target validator uid, only among permitted validators, by highest trust. + // let pick_target_uid = |trust: &Vec, permit: &Vec| -> Option { + // let mut best_uid: Option = None; + // let mut best_trust: u16 = 0; + // for (i, (&t, &p)) in trust.iter().zip(permit.iter()).enumerate() { + // if p && (best_uid.is_none() || t > best_trust) { + // best_uid = Some(i); + // best_trust = t; + // } + // } + // best_uid.map(|i| i as u16) + // }; + + // for CloseItem { owner, pos_id } in to_close.into_iter() { + // match Self::do_remove_liquidity(netuid, &owner, pos_id) { + // Ok(rm) => { + // weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 6)); + // // α withdrawn from the pool = principal + accrued fees + // let alpha_total_from_pool: AlphaBalance = + // rm.alpha.saturating_add(rm.fee_alpha); + + // // ---------------- USER: refund τ and convert α → stake ---------------- + + // // 1) Refund τ principal directly. + // let tao_total_from_pool: TaoBalance = rm.tao.saturating_add(rm.fee_tao); + // if tao_total_from_pool > TaoBalance::ZERO { + // T::BalanceOps::increase_balance(&owner, tao_total_from_pool); + // weight.saturating_accrue(T::DbWeight::get().writes(1)); + // user_refunded_tao = + // user_refunded_tao.saturating_add(tao_total_from_pool); + // T::TaoReserve::decrease_provided(netuid, tao_total_from_pool); + // weight.saturating_accrue(T::DbWeight::get().writes(1)); + // } + + // // 2) Stake ALL withdrawn α (principal + fees) to the best permitted validator. + // if alpha_total_from_pool > AlphaBalance::ZERO { + // if let Some(target_uid) = pick_target_uid(&trust, &permit) { + // let validator_hotkey: T::AccountId = + // T::SubnetInfo::hotkey_of_uid(netuid.into(), target_uid).ok_or( + // sp_runtime::DispatchError::Other( + // "validator_hotkey_missing", + // ), + // )?; + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + + // // Stake α from LP owner (coldkey) to chosen validator (hotkey). + // T::BalanceOps::increase_stake( + // &owner, + // &validator_hotkey, + // netuid, + // alpha_total_from_pool, + // )?; + // weight.saturating_accrue(T::DbWeight::get().writes(1)); + // user_staked_alpha = + // user_staked_alpha.saturating_add(alpha_total_from_pool); + + // log::debug!( + // "dissolve_all_lp: user dissolved & staked α: netuid={netuid:?}, owner={owner:?}, pos_id={pos_id:?}, α_staked={alpha_total_from_pool:?}, target_uid={target_uid}" + // ); + // } else { + // // No permitted validators; burn to avoid balance drift. + // log::debug!( + // "dissolve_all_lp: no permitted validators; α burned: netuid={netuid:?}, owner={owner:?}, pos_id={pos_id:?}, α_total={alpha_total_from_pool:?}" + // ); + // } + + // T::AlphaReserve::decrease_provided(netuid, alpha_total_from_pool); + // weight.saturating_accrue(T::DbWeight::get().writes(1)); + // } + // } + // Err(e) => { + // log::debug!( + // "dissolve_all_lp: force-close failed: netuid={netuid:?}, owner={owner:?}, pos_id={pos_id:?}, err={e:?}" + // ); + // weight.saturating_accrue(T::DbWeight::get().reads(1)); + // continue; + // } + // } + // } + + // log::debug!( + // "dissolve_all_liquidity_providers (users-only): netuid={netuid:?}, users_refunded_total_τ={user_refunded_tao:?}, users_staked_total_α={user_staked_alpha:?}; protocol liquidity untouched" + // ); + + // return Ok(Some(weight).into()); + // } + + // log::debug!( + // "dissolve_all_liquidity_providers: netuid={netuid:?}, mode=V2-or-nonV3, leaving all liquidity/state intact" + // ); Ok(Some(weight).into()) } diff --git a/pallets/swap/src/pallet/mod.rs b/pallets/swap/src/pallet/mod.rs index 95a82a1c08..7a239a1d77 100644 --- a/pallets/swap/src/pallet/mod.rs +++ b/pallets/swap/src/pallet/mod.rs @@ -1,12 +1,11 @@ use core::num::NonZeroU64; -use core::ops::Neg; use frame_support::{PalletId, pallet_prelude::*, traits::Get}; use frame_system::pallet_prelude::*; use sp_arithmetic::Perbill; use substrate_fixed::types::U64F64; use subtensor_runtime_common::{ - AlphaBalance, BalanceOps, NetUid, SubnetInfo, TaoBalance, Token, TokenReserve, + AlphaBalance, BalanceOps, NetUid, SubnetInfo, TaoBalance, TokenReserve, }; use crate::{ @@ -463,49 +462,51 @@ mod pallet { #[pallet::call_index(2)] #[pallet::weight(::WeightInfo::remove_liquidity())] pub fn remove_liquidity( - origin: OriginFor, - hotkey: T::AccountId, - netuid: NetUid, - position_id: PositionId, + _origin: OriginFor, + _hotkey: T::AccountId, + _netuid: NetUid, + _position_id: PositionId, ) -> DispatchResult { - let coldkey = ensure_signed(origin)?; + // Deprecated by balancer - // Ensure that the subnet exists. - ensure!( - T::SubnetInfo::exists(netuid.into()), - Error::::MechanismDoesNotExist - ); + // let coldkey = ensure_signed(origin)?; + + // // Ensure that the subnet exists. + // ensure!( + // T::SubnetInfo::exists(netuid.into()), + // Error::::MechanismDoesNotExist + // ); + + // // Remove liquidity + // let result = Self::do_remove_liquidity(netuid, &coldkey, position_id)?; + + // // Credit the returned tao and alpha to the account + // T::BalanceOps::increase_balance(&coldkey, result.tao.saturating_add(result.fee_tao)); + // T::BalanceOps::increase_stake( + // &coldkey, + // &hotkey, + // netuid.into(), + // result.alpha.saturating_add(result.fee_alpha), + // )?; - // Remove liquidity - let result = Self::do_remove_liquidity(netuid, &coldkey, position_id)?; - - // Credit the returned tao and alpha to the account - T::BalanceOps::increase_balance(&coldkey, result.tao.saturating_add(result.fee_tao)); - T::BalanceOps::increase_stake( - &coldkey, - &hotkey, - netuid.into(), - result.alpha.saturating_add(result.fee_alpha), - )?; - - // Remove withdrawn liquidity from user-provided reserves - T::TaoReserve::decrease_provided(netuid.into(), result.tao); - T::AlphaReserve::decrease_provided(netuid.into(), result.alpha); - - // Emit an event - Self::deposit_event(Event::LiquidityRemoved { - coldkey, - hotkey, - netuid: netuid.into(), - position_id, - liquidity: result.liquidity, - tao: result.tao, - alpha: result.alpha, - fee_tao: result.fee_tao, - fee_alpha: result.fee_alpha, - tick_low: result.tick_low.into(), - tick_high: result.tick_high.into(), - }); + // // Remove withdrawn liquidity from user-provided reserves + // T::TaoReserve::decrease_provided(netuid.into(), result.tao); + // T::AlphaReserve::decrease_provided(netuid.into(), result.alpha); + + // // Emit an event + // Self::deposit_event(Event::LiquidityRemoved { + // coldkey, + // hotkey, + // netuid: netuid.into(), + // position_id, + // liquidity: result.liquidity, + // tao: result.tao, + // alpha: result.alpha, + // fee_tao: result.fee_tao, + // fee_alpha: result.fee_alpha, + // tick_low: result.tick_low.into(), + // tick_high: result.tick_high.into(), + // }); Ok(()) } @@ -522,99 +523,101 @@ mod pallet { #[pallet::call_index(3)] #[pallet::weight(::WeightInfo::modify_position())] pub fn modify_position( - origin: OriginFor, - hotkey: T::AccountId, - netuid: NetUid, - position_id: PositionId, - liquidity_delta: i64, + _origin: OriginFor, + _hotkey: T::AccountId, + _netuid: NetUid, + _position_id: PositionId, + _liquidity_delta: i64, ) -> DispatchResult { - let coldkey = ensure_signed(origin)?; + // Deprecated by balancer - // Ensure that the subnet exists. - ensure!( - T::SubnetInfo::exists(netuid.into()), - Error::::MechanismDoesNotExist - ); + // let coldkey = ensure_signed(origin)?; - ensure!( - T::SubnetInfo::is_subtoken_enabled(netuid.into()), - Error::::SubtokenDisabled - ); + // // Ensure that the subnet exists. + // ensure!( + // T::SubnetInfo::exists(netuid.into()), + // Error::::MechanismDoesNotExist + // ); - // Add or remove liquidity - let result = - Self::do_modify_position(netuid, &coldkey, &hotkey, position_id, liquidity_delta)?; - - if liquidity_delta > 0 { - // Remove TAO and Alpha balances or fail transaction if they can't be removed exactly - let tao_provided = T::BalanceOps::decrease_balance(&coldkey, result.tao)?; - ensure!(tao_provided == result.tao, Error::::InsufficientBalance); - - T::BalanceOps::decrease_stake(&coldkey, &hotkey, netuid.into(), result.alpha)?; - - // Emit an event - Self::deposit_event(Event::LiquidityModified { - coldkey: coldkey.clone(), - hotkey: hotkey.clone(), - netuid, - position_id, - liquidity: liquidity_delta, - tao: result.tao.to_u64() as i64, - alpha: result.alpha.to_u64() as i64, - fee_tao: result.fee_tao, - fee_alpha: result.fee_alpha, - tick_low: result.tick_low, - tick_high: result.tick_high, - }); - } else { - // Credit the returned tao and alpha to the account - T::BalanceOps::increase_balance(&coldkey, result.tao); - T::BalanceOps::increase_stake(&coldkey, &hotkey, netuid.into(), result.alpha)?; - - // Emit an event - if result.removed { - Self::deposit_event(Event::LiquidityRemoved { - coldkey: coldkey.clone(), - hotkey: hotkey.clone(), - netuid, - position_id, - liquidity: liquidity_delta.unsigned_abs(), - tao: result.tao, - alpha: result.alpha, - fee_tao: result.fee_tao, - fee_alpha: result.fee_alpha, - tick_low: result.tick_low, - tick_high: result.tick_high, - }); - } else { - Self::deposit_event(Event::LiquidityModified { - coldkey: coldkey.clone(), - hotkey: hotkey.clone(), - netuid, - position_id, - liquidity: liquidity_delta, - tao: (result.tao.to_u64() as i64).neg(), - alpha: (result.alpha.to_u64() as i64).neg(), - fee_tao: result.fee_tao, - fee_alpha: result.fee_alpha, - tick_low: result.tick_low, - tick_high: result.tick_high, - }); - } - } + // ensure!( + // T::SubnetInfo::is_subtoken_enabled(netuid.into()), + // Error::::SubtokenDisabled + // ); - // Credit accrued fees to user account (no matter if liquidity is added or removed) - if result.fee_tao > TaoBalance::ZERO { - T::BalanceOps::increase_balance(&coldkey, result.fee_tao); - } - if !result.fee_alpha.is_zero() { - T::BalanceOps::increase_stake( - &coldkey, - &hotkey.clone(), - netuid.into(), - result.fee_alpha, - )?; - } + // // Add or remove liquidity + // let result = + // Self::do_modify_position(netuid, &coldkey, &hotkey, position_id, liquidity_delta)?; + + // if liquidity_delta > 0 { + // // Remove TAO and Alpha balances or fail transaction if they can't be removed exactly + // let tao_provided = T::BalanceOps::decrease_balance(&coldkey, result.tao)?; + // ensure!(tao_provided == result.tao, Error::::InsufficientBalance); + + // T::BalanceOps::decrease_stake(&coldkey, &hotkey, netuid.into(), result.alpha)?; + + // // Emit an event + // Self::deposit_event(Event::LiquidityModified { + // coldkey: coldkey.clone(), + // hotkey: hotkey.clone(), + // netuid, + // position_id, + // liquidity: liquidity_delta, + // tao: result.tao.to_u64() as i64, + // alpha: result.alpha.to_u64() as i64, + // fee_tao: result.fee_tao, + // fee_alpha: result.fee_alpha, + // tick_low: result.tick_low, + // tick_high: result.tick_high, + // }); + // } else { + // // Credit the returned tao and alpha to the account + // T::BalanceOps::increase_balance(&coldkey, result.tao); + // T::BalanceOps::increase_stake(&coldkey, &hotkey, netuid.into(), result.alpha)?; + + // // Emit an event + // if result.removed { + // Self::deposit_event(Event::LiquidityRemoved { + // coldkey: coldkey.clone(), + // hotkey: hotkey.clone(), + // netuid, + // position_id, + // liquidity: liquidity_delta.unsigned_abs(), + // tao: result.tao, + // alpha: result.alpha, + // fee_tao: result.fee_tao, + // fee_alpha: result.fee_alpha, + // tick_low: result.tick_low, + // tick_high: result.tick_high, + // }); + // } else { + // Self::deposit_event(Event::LiquidityModified { + // coldkey: coldkey.clone(), + // hotkey: hotkey.clone(), + // netuid, + // position_id, + // liquidity: liquidity_delta, + // tao: (result.tao.to_u64() as i64).neg(), + // alpha: (result.alpha.to_u64() as i64).neg(), + // fee_tao: result.fee_tao, + // fee_alpha: result.fee_alpha, + // tick_low: result.tick_low, + // tick_high: result.tick_high, + // }); + // } + // } + + // // Credit accrued fees to user account (no matter if liquidity is added or removed) + // if result.fee_tao > TaoBalance::ZERO { + // T::BalanceOps::increase_balance(&coldkey, result.fee_tao); + // } + // if !result.fee_alpha.is_zero() { + // T::BalanceOps::increase_stake( + // &coldkey, + // &hotkey.clone(), + // netuid.into(), + // result.fee_alpha, + // )?; + // } Ok(()) } diff --git a/pallets/swap/src/pallet/tests.rs b/pallets/swap/src/pallet/tests.rs index e2b53c5142..5d75c7da27 100644 --- a/pallets/swap/src/pallet/tests.rs +++ b/pallets/swap/src/pallet/tests.rs @@ -2191,78 +2191,6 @@ fn test_liquidate_idempotent() { }); } -#[test] -fn liquidate_v3_refunds_user_funds_and_clears_state() { - new_test_ext().execute_with(|| { - let netuid = NetUid::from(1); - - // Enable V3 path & initialize price/ticks (also creates a protocol position). - assert_ok!(Pallet::::toggle_user_liquidity( - RuntimeOrigin::root(), - netuid, - true - )); - assert_ok!(Pallet::::maybe_initialize_v3(netuid)); - - // Use distinct cold/hot to demonstrate alpha refund/stake accounting. - let cold = OK_COLDKEY_ACCOUNT_ID; - let hot = OK_HOTKEY_ACCOUNT_ID; - - // Tight in‑range band around current tick. - let ct = CurrentTick::::get(netuid); - let tick_low = ct.saturating_sub(10); - let tick_high = ct.saturating_add(10); - let liquidity: u64 = 1_000_000; - - // Snapshot balances BEFORE. - let tao_before = ::BalanceOps::tao_balance(&cold); - let alpha_before_hot = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &hot); - let alpha_before_owner = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &cold); - let alpha_before_total = alpha_before_hot + alpha_before_owner; - - // Create the user position (storage & v3 state only; no balances moved yet). - let (_pos_id, need_tao, need_alpha) = - Pallet::::do_add_liquidity(netuid, &cold, &hot, tick_low, tick_high, liquidity) - .expect("add liquidity"); - - // Mirror extrinsic bookkeeping: withdraw funds & bump provided‑reserve counters. - let tao_taken = ::BalanceOps::decrease_balance(&cold, need_tao.into()) - .expect("decrease TAO"); - ::BalanceOps::decrease_stake(&cold, &hot, netuid.into(), need_alpha.into()) - .expect("decrease ALPHA"); - TaoReserve::increase_provided(netuid.into(), tao_taken); - AlphaReserve::increase_provided(netuid.into(), need_alpha.into()); - - // Users‑only liquidation. - assert_ok!(Pallet::::do_dissolve_all_liquidity_providers(netuid)); - - // Expect balances restored to BEFORE snapshots (no swaps ran -> zero fees). - let tao_after = ::BalanceOps::tao_balance(&cold); - assert_eq!(tao_after, tao_before, "TAO principal must be refunded"); - - // ALPHA totals conserved to owner (distribution may differ). - let alpha_after_hot = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &hot); - let alpha_after_owner = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &cold); - let alpha_after_total = alpha_after_hot + alpha_after_owner; - assert_eq!( - alpha_after_total, alpha_before_total, - "ALPHA principal must be refunded/staked for the account (check totals)" - ); - - // Clear protocol liquidity and V3 state now. - assert_ok!(Pallet::::do_clear_protocol_liquidity(netuid)); - - // User position(s) are gone and all V3 state cleared. - assert_eq!(Pallet::::count_positions(netuid, &cold), 0); - assert!(Ticks::::iter_prefix(netuid).next().is_none()); - assert!(!SwapV3Initialized::::contains_key(netuid)); - }); -} - #[test] fn refund_alpha_single_provider_exact() { new_test_ext().execute_with(|| { @@ -2451,171 +2379,6 @@ fn refund_alpha_same_cold_multiple_hotkeys_conserved_to_owner() { }); } -#[test] -fn test_dissolve_v3_green_path_refund_tao_stake_alpha_and_clear_state() { - new_test_ext().execute_with(|| { - // --- Setup --- - let netuid = NetUid::from(42); - let cold = OK_COLDKEY_ACCOUNT_ID; - let hot = OK_HOTKEY_ACCOUNT_ID; - - assert_ok!(Swap::toggle_user_liquidity( - RuntimeOrigin::root(), - netuid.into(), - true - )); - assert_ok!(Pallet::::maybe_initialize_v3(netuid)); - assert!(SwapV3Initialized::::get(netuid)); - - // Tight in‑range band so BOTH τ and α are required. - let ct = CurrentTick::::get(netuid); - let tick_low = ct.saturating_sub(10); - let tick_high = ct.saturating_add(10); - let liquidity: u64 = 1_250_000; - - // Add liquidity and capture required τ/α. - let (_pos_id, tao_needed, alpha_needed) = - Pallet::::do_add_liquidity(netuid, &cold, &hot, tick_low, tick_high, liquidity) - .expect("add in-range liquidity"); - assert!(tao_needed > 0, "in-range pos must require TAO"); - assert!(alpha_needed > 0, "in-range pos must require ALPHA"); - - // Determine the permitted validator with the highest trust (green path). - let trust = ::SubnetInfo::get_validator_trust(netuid.into()); - let permit = ::SubnetInfo::get_validator_permit(netuid.into()); - assert_eq!(trust.len(), permit.len(), "trust/permit must align"); - let target_uid: u16 = trust - .iter() - .zip(permit.iter()) - .enumerate() - .filter(|(_, (_t, p))| **p) - .max_by_key(|(_, (t, _))| *t) - .map(|(i, _)| i as u16) - .expect("at least one permitted validator"); - let validator_hotkey: ::AccountId = - ::SubnetInfo::hotkey_of_uid(netuid.into(), target_uid) - .expect("uid -> hotkey mapping must exist"); - - // --- Snapshot BEFORE we withdraw τ/α to fund the position --- - let tao_before = ::BalanceOps::tao_balance(&cold); - - let alpha_before_hot = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &hot); - let alpha_before_owner = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &cold); - let alpha_before_val = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &validator_hotkey); - - let alpha_before_total = if validator_hotkey == hot { - alpha_before_hot + alpha_before_owner - } else { - alpha_before_hot + alpha_before_owner + alpha_before_val - }; - - // --- Mirror extrinsic bookkeeping: withdraw τ & α; bump provided reserves --- - let tao_taken = ::BalanceOps::decrease_balance(&cold, tao_needed.into()) - .expect("decrease TAO"); - ::BalanceOps::decrease_stake( - &cold, - &hot, - netuid.into(), - alpha_needed.into(), - ) - .expect("decrease ALPHA"); - - TaoReserve::increase_provided(netuid.into(), tao_taken); - AlphaReserve::increase_provided(netuid.into(), alpha_needed.into()); - - // --- Act: dissolve (GREEN PATH: permitted validators exist) --- - assert_ok!(Pallet::::do_dissolve_all_liquidity_providers(netuid)); - - // --- Assert: τ principal refunded to user --- - let tao_after = ::BalanceOps::tao_balance(&cold); - assert_eq!(tao_after, tao_before, "TAO principal must be refunded"); - - // --- α ledger assertions --- - let alpha_after_hot = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &hot); - let alpha_after_owner = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &cold); - let alpha_after_val = - ::BalanceOps::alpha_balance(netuid.into(), &cold, &validator_hotkey); - - // Owner ledger must be unchanged in the green path. - assert_eq!( - alpha_after_owner, alpha_before_owner, - "Owner α ledger must be unchanged (staked to validator, not refunded)" - ); - - if validator_hotkey == hot { - assert_eq!( - alpha_after_hot, alpha_before_hot, - "When validator == hotkey, user's hot ledger must net back to its original balance" - ); - let alpha_after_total = alpha_after_hot + alpha_after_owner; - assert_eq!( - alpha_after_total, alpha_before_total, - "Total α for the coldkey must be conserved (validator==hotkey)" - ); - } else { - assert!( - alpha_before_hot >= alpha_after_hot, - "hot ledger should not increase" - ); - assert!( - alpha_after_val >= alpha_before_val, - "validator ledger should not decrease" - ); - - let hot_loss = alpha_before_hot - alpha_after_hot; - let val_gain = alpha_after_val - alpha_before_val; - assert_eq!( - val_gain, hot_loss, - "α that left the user's hot ledger must equal α credited to the validator ledger" - ); - - let alpha_after_total = alpha_after_hot + alpha_after_owner + alpha_after_val; - assert_eq!( - alpha_after_total, alpha_before_total, - "Total α for the coldkey must be conserved" - ); - } - - // Now clear protocol liquidity & state and assert full reset. - assert_ok!(Pallet::::do_clear_protocol_liquidity(netuid)); - - let protocol_id = Pallet::::protocol_account_id(); - assert_eq!(Pallet::::count_positions(netuid, &cold), 0); - let prot_positions_after = - Positions::::iter_prefix_values((netuid, protocol_id)).collect::>(); - assert!( - prot_positions_after.is_empty(), - "protocol positions must be removed" - ); - - assert!(Ticks::::iter_prefix(netuid).next().is_none()); - assert!(Ticks::::get(netuid, TickIndex::MIN).is_none()); - assert!(Ticks::::get(netuid, TickIndex::MAX).is_none()); - assert!(!CurrentLiquidity::::contains_key(netuid)); - assert!(!CurrentTick::::contains_key(netuid)); - assert!(!AlphaSqrtPrice::::contains_key(netuid)); - assert!(!SwapV3Initialized::::contains_key(netuid)); - - assert!(!FeeGlobalTao::::contains_key(netuid)); - assert!(!FeeGlobalAlpha::::contains_key(netuid)); - - assert!( - TickIndexBitmapWords::::iter_prefix((netuid,)) - .next() - .is_none(), - "active tick bitmap words must be cleared" - ); - - assert!(!FeeRate::::contains_key(netuid)); - assert!(!EnabledUserLiquidity::::contains_key(netuid)); - }); -} - #[test] fn test_clear_protocol_liquidity_green_path() { new_test_ext().execute_with(|| { diff --git a/pallets/transaction-fee/src/lib.rs b/pallets/transaction-fee/src/lib.rs index 068867ddd4..3f75eb4984 100644 --- a/pallets/transaction-fee/src/lib.rs +++ b/pallets/transaction-fee/src/lib.rs @@ -111,6 +111,7 @@ where /// Handle Alpha fees impl AlphaFeeHandler for TransactionFeeHandler where + T: AuthorshipInfo>, T: frame_system::Config, T: pallet_subtensor::Config, T: pallet_subtensor_swap::Config, @@ -174,18 +175,23 @@ where let alpha_fee = alpha_equivalent.min(alpha_balance); // Sell alpha_fee and burn received tao (ignore unstake_from_subnet return). - let swap_result = pallet_subtensor::Pallet::::unstake_from_subnet( - hotkey, - coldkey, - *netuid, - alpha_fee, - 0.into(), - true, - ); - - if let Ok(tao_amount) = swap_result { - (alpha_fee, tao_amount) + if let Some(author) = T::author() { + let swap_result = pallet_subtensor::Pallet::::unstake_from_subnet( + hotkey, + coldkey, + &author, + *netuid, + alpha_fee, + 0.into(), + true, + ); + if let Ok(tao_amount) = swap_result { + (alpha_fee, tao_amount) + } else { + (0.into(), 0.into()) + } } else { + // Fallback: no author => no fees (do nothing) (0.into(), 0.into()) } } else { @@ -406,13 +412,7 @@ where OU::on_unbalanceds(Some(fee).into_iter().chain(Some(tip))); } WithdrawnFee::Alpha((alpha_fee, tao_amount)) => { - if let Some(author) = T::author() { - // Pay block author - let _ = F::deposit(&author, tao_amount.into(), Precision::BestEffort) - .unwrap_or_else(|_| Debt::::zero()); - } else { - // Fallback: no author => do nothing - } + // Block author already received the fee in withdraw_in_alpha, nothing to do here. frame_system::Pallet::::deposit_event( pallet_subtensor::Event::::TransactionFeePaidWithAlpha { who: who.clone(), diff --git a/pallets/transaction-fee/src/tests/mock.rs b/pallets/transaction-fee/src/tests/mock.rs index a897e82cb6..b256e05660 100644 --- a/pallets/transaction-fee/src/tests/mock.rs +++ b/pallets/transaction-fee/src/tests/mock.rs @@ -229,6 +229,8 @@ parameter_types! { pub const LeaseDividendsDistributionInterval: u32 = 100; // 100 blocks pub const MaxImmuneUidsPercentage: Percent = Percent::from_percent(80); pub const EvmKeyAssociateRateLimit: u64 = 0; + pub const SubtensorPalletId: PalletId = PalletId(*b"subtensr"); + pub const BurnAccountId: PalletId = PalletId(*b"burntnsr"); } impl pallet_subtensor::Config for Test { @@ -304,6 +306,8 @@ impl pallet_subtensor::Config for Test { type CommitmentsInterface = CommitmentsI; type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit; type AuthorshipProvider = MockAuthorshipProvider; + type SubtensorPalletId = SubtensorPalletId; + type BurnAccountId = BurnAccountId; type WeightInfo = (); } @@ -605,7 +609,7 @@ pub fn register_ok_neuron( let bal: TaoBalance = SubtensorModule::get_coldkey_balance(&cold); if bal < min_balance_needed { - SubtensorModule::add_balance_to_coldkey_account(&cold, min_balance_needed - bal); + add_balance_to_coldkey_account(&cold, min_balance_needed - bal); } }; @@ -642,11 +646,22 @@ pub fn register_ok_neuron( ); } +#[allow(dead_code)] +pub fn add_balance_to_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao).unwrap(); +} + +#[allow(dead_code)] +pub fn remove_balance_from_coldkey_account(coldkey: &U256, tao: TaoBalance) { + let _ = SubtensorModule::burn_tao(coldkey, tao); +} + #[allow(dead_code)] pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); - SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost.into()); + add_balance_to_coldkey_account(coldkey, lock_cost.into()); assert_ok!(SubtensorModule::register_network( RawOrigin::Signed(*coldkey).into(), @@ -813,7 +828,7 @@ pub fn setup_stake( stake_amount: u64, ) { // Fund enough to stake while keeping the coldkey account alive (KeepAlive / ED). - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( coldkey, TaoBalance::from(stake_amount) + ExistentialDeposit::get(), ); @@ -868,6 +883,7 @@ pub(crate) fn quote_remove_stake_after_alpha_fee( assert_ok!(SubtensorModule::unstake_from_subnet( hotkey, coldkey, + coldkey, netuid, alpha_fee, 0.into(), diff --git a/pallets/transaction-fee/src/tests/mod.rs b/pallets/transaction-fee/src/tests/mod.rs index 48af6075b1..472757f720 100644 --- a/pallets/transaction-fee/src/tests/mod.rs +++ b/pallets/transaction-fee/src/tests/mod.rs @@ -53,8 +53,8 @@ fn test_remove_stake_fees_tao() { let register_prefund = stake_amount .saturating_mul(10_000.into()) // generous buffer .saturating_add(ExistentialDeposit::get()); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(10000), register_prefund); - SubtensorModule::add_balance_to_coldkey_account(&U256::from(20001), register_prefund); + add_balance_to_coldkey_account(&U256::from(10000), register_prefund); + add_balance_to_coldkey_account(&U256::from(20001), register_prefund); let sn = setup_subnets(1, 1); @@ -67,7 +67,7 @@ fn test_remove_stake_fees_tao() { &sn.hotkeys[0], stake_amount.into(), ); - SubtensorModule::add_balance_to_coldkey_account(&sn.coldkey, TaoBalance::from(TAO)); + add_balance_to_coldkey_account(&sn.coldkey, TaoBalance::from(TAO)); // Avoid staking-op rate limit between add_stake and remove_stake. jump_blocks(1_000_001); @@ -230,7 +230,7 @@ fn test_remove_stake_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -346,10 +346,7 @@ fn test_remove_stake_root() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( - &coldkey, - current_balance - ExistentialDeposit::get(), - ); + remove_balance_from_coldkey_account(&coldkey, current_balance - ExistentialDeposit::get()); // Remove stake let balance_before = Balances::free_balance(coldkey); @@ -404,10 +401,7 @@ fn test_remove_stake_completely_root() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( - &coldkey, - current_balance - ExistentialDeposit::get(), - ); + remove_balance_from_coldkey_account(&coldkey, current_balance - ExistentialDeposit::get()); // Remove stake let balance_before = Balances::free_balance(coldkey); @@ -461,13 +455,15 @@ fn test_remove_stake_completely_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); // Remove stake let balance_before = Balances::free_balance(sn.coldkey); + println!("========== debug balance_before: {:?}", balance_before); + let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::remove_stake { hotkey: sn.hotkeys[0], netuid: sn.subnets[0].netuid, @@ -492,6 +488,12 @@ fn test_remove_stake_completely_fees_alpha() { sn.subnets[0].netuid, ); + println!( + "========== debug expected_unstaked_tao: {:?}", + expected_unstaked_tao + ); + println!("========== debug final_balance: {:?}", final_balance); + // Effectively, the fee is paid in TAO in this case because user receives less TAO, // and all Alpha is gone, and it is not measurable in Alpha let actual_fee = balance_before + expected_unstaked_tao.into() - final_balance; @@ -508,7 +510,7 @@ fn test_remove_stake_not_enough_balance_for_fees() { let stake_amount = TaoBalance::from(TAO); let sn = setup_subnets(1, 1); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &sn.coldkey, stake_amount .saturating_mul(2.into()) // buffer so staking doesn't attempt to drain the account @@ -530,7 +532,7 @@ fn test_remove_stake_not_enough_balance_for_fees() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -596,7 +598,7 @@ fn test_remove_stake_edge_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -661,7 +663,7 @@ fn test_remove_stake_failing_transaction_tao_fees() { let unstake_amount = AlphaBalance::from(TAO / 50); let sn = setup_subnets(1, 1); - SubtensorModule::add_balance_to_coldkey_account( + add_balance_to_coldkey_account( &sn.coldkey, stake_amount .saturating_mul(2.into()) // buffer so staking doesn't attempt to drain the account @@ -674,7 +676,7 @@ fn test_remove_stake_failing_transaction_tao_fees() { stake_amount.into(), )); - SubtensorModule::add_balance_to_coldkey_account(&sn.coldkey, TAO.into()); + add_balance_to_coldkey_account(&sn.coldkey, TAO.into()); // Make unstaking fail by reducing liquidity to critical SubnetTAO::::insert(sn.subnets[0].netuid, TaoBalance::from(1)); @@ -743,7 +745,7 @@ fn test_remove_stake_failing_transaction_alpha_fees() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -808,7 +810,7 @@ fn test_remove_stake_limit_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -910,10 +912,7 @@ fn test_unstake_all_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( - &coldkey, - current_balance - ExistentialDeposit::get(), - ); + remove_balance_from_coldkey_account(&coldkey, current_balance - ExistentialDeposit::get()); // Unstake all let balance_before = Balances::free_balance(sn.coldkey); @@ -937,7 +936,7 @@ fn test_unstake_all_fees_alpha() { ); // Give the coldkey TAO balance - now should unstake ok - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_u64.into()); assert_ok!(ext.dispatch_transaction( RuntimeOrigin::signed(coldkey).into(), call, @@ -991,10 +990,7 @@ fn test_unstake_all_alpha_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( - &coldkey, - current_balance - ExistentialDeposit::get(), - ); + remove_balance_from_coldkey_account(&coldkey, current_balance - ExistentialDeposit::get()); // Unstake all let balance_before = Balances::free_balance(sn.coldkey); @@ -1018,7 +1014,7 @@ fn test_unstake_all_alpha_fees_alpha() { ); // Give the coldkey TAO balance - now should unstake ok - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_u64.into()); + add_balance_to_coldkey_account(&coldkey, 1_000_000_000_u64.into()); assert_ok!(ext.dispatch_transaction( RuntimeOrigin::signed(coldkey).into(), call, @@ -1062,7 +1058,7 @@ fn test_move_stake_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -1134,7 +1130,7 @@ fn test_transfer_stake_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -1205,7 +1201,7 @@ fn test_swap_stake_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -1275,7 +1271,7 @@ fn test_swap_stake_limit_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -1347,7 +1343,7 @@ fn test_burn_alpha_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -1408,7 +1404,7 @@ fn test_recycle_alpha_fees_alpha() { // Forse-set signer balance to ED let current_balance = Balances::free_balance(sn.coldkey); - let _ = SubtensorModule::remove_balance_from_coldkey_account( + remove_balance_from_coldkey_account( &sn.coldkey, current_balance - ExistentialDeposit::get(), ); @@ -1470,7 +1466,7 @@ fn test_add_stake_fees_go_to_block_builder() { // Simulate add stake to get the expected TAO fee let (_, swap_fee) = mock::swap_tao_to_alpha(sn.subnets[0].netuid, stake_amount.into()); - SubtensorModule::add_balance_to_coldkey_account(&sn.coldkey, (stake_amount * 10).into()); + add_balance_to_coldkey_account(&sn.coldkey, (stake_amount * 10).into()); remove_stake_rate_limit_for_tests(&sn.hotkeys[0], &sn.coldkey, sn.subnets[0].netuid); // Stake diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 2bf078a199..ffa654941b 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1124,6 +1124,8 @@ parameter_types! { pub const LeaseDividendsDistributionInterval: BlockNumber = 100; // 100 blocks pub const MaxImmuneUidsPercentage: Percent = Percent::from_percent(80); pub const EvmKeyAssociateRateLimit: u64 = EVM_KEY_ASSOCIATE_RATELIMIT; + pub const SubtensorPalletId: PalletId = PalletId(*b"subtensr"); + pub const BurnAccountId: PalletId = PalletId(*b"burntnsr"); } impl pallet_subtensor::Config for Runtime { @@ -1199,6 +1201,8 @@ impl pallet_subtensor::Config for Runtime { type CommitmentsInterface = CommitmentsI; type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit; type AuthorshipProvider = BlockAuthorFromAura; + type SubtensorPalletId = SubtensorPalletId; + type BurnAccountId = BurnAccountId; type WeightInfo = pallet_subtensor::weights::SubstrateWeight; } @@ -2508,6 +2512,10 @@ impl_runtime_apis! { fn get_selective_mechagraph(netuid: NetUid, mecid: MechId, metagraph_indexes: Vec) -> Option> { SubtensorModule::get_selective_mechagraph(netuid, mecid, metagraph_indexes) } + + fn get_subnet_account_id(netuid: NetUid) -> Option { + SubtensorModule::get_subnet_account_id(netuid) + } } impl subtensor_custom_rpc_runtime_api::StakeInfoRuntimeApi for Runtime { diff --git a/runtime/tests/account_conversion.rs b/runtime/tests/account_conversion.rs new file mode 100644 index 0000000000..11aad3da85 --- /dev/null +++ b/runtime/tests/account_conversion.rs @@ -0,0 +1,53 @@ +#![allow(clippy::unwrap_used)] + +use node_subtensor_runtime::{BuildStorage, RuntimeGenesisConfig, SubtensorModule, System}; +use subtensor_runtime_common::NetUid; + +fn new_test_ext() -> sp_io::TestExternalities { + sp_tracing::try_init_simple(); + let mut ext: sp_io::TestExternalities = RuntimeGenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![], + dev_accounts: None, + }, + ..Default::default() + } + .build_storage() + .unwrap() + .into(); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +/// Test full-range netuids on real ss58 accounts to ensure no panics +/// cargo test --package node-subtensor-runtime --test account_conversion -- test_subnet_account_id_no_panics --exact --nocapture +#[test] +#[ignore] +fn test_subnet_account_id_no_panics() { + new_test_ext().execute_with(|| { + for raw_netuid in 0u16..=u16::MAX { + let netuid = NetUid::from(raw_netuid); + SubtensorModule::init_new_network(netuid, 10); + + let account_id = SubtensorModule::get_subnet_account_id(netuid).unwrap(); + let roudtrip_netuid = SubtensorModule::is_subnet_account_id(&account_id); + assert_eq!(netuid, roudtrip_netuid.unwrap()); + } + }); +} + +/// Quick sanity test +/// cargo test --package node-subtensor-runtime --test account_conversion -- test_subnet_account_id_no_panics_quick --exact --nocapture +#[test] +fn test_subnet_account_id_no_panics_quick() { + new_test_ext().execute_with(|| { + for raw_netuid in 0u16..=1024u16 { + let netuid = NetUid::from(raw_netuid); + SubtensorModule::init_new_network(netuid, 10); + + let account_id = SubtensorModule::get_subnet_account_id(netuid).unwrap(); + let roudtrip_netuid = SubtensorModule::is_subnet_account_id(&account_id); + assert_eq!(netuid, roudtrip_netuid.unwrap()); + } + }); +} diff --git a/runtime/tests/precompiles.rs b/runtime/tests/precompiles.rs index 815d055ab7..32036bd109 100644 --- a/runtime/tests/precompiles.rs +++ b/runtime/tests/precompiles.rs @@ -103,6 +103,7 @@ mod address_mapping { mod balance_transfer { use super::*; + use subtensor_runtime_common::TaoBalance; fn balance_transfer_call_data(target: H256) -> Vec { // Solidity selector for transfer(bytes32). @@ -113,6 +114,11 @@ mod balance_transfer { input } + fn add_balance_to_coldkey_account(coldkey: &AccountId, tao: TaoBalance) { + let credit = pallet_subtensor::Pallet::::mint_tao(tao); + let _ = pallet_subtensor::Pallet::::spend_tao(coldkey, credit, tao).unwrap(); + } + #[test] fn balance_transfer_precompile_transfers_balance() { new_test_ext().execute_with(|| { @@ -123,10 +129,7 @@ mod balance_transfer { let destination_account: AccountId = destination_raw.0.into(); let amount = 123_456; - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &dispatch_account, - (amount * 2).into(), - ); + add_balance_to_coldkey_account(&dispatch_account, (amount * 2).into()); let source_balance_before = pallet_balances::Pallet::::free_balance(&dispatch_account); @@ -167,10 +170,7 @@ mod balance_transfer { let destination_account: AccountId = destination_raw.0.into(); let amount = 100; - pallet_subtensor::Pallet::::add_balance_to_coldkey_account( - &dispatch_account, - 1_000_000_u64.into(), - ); + add_balance_to_coldkey_account(&dispatch_account, 1_000_000_u64.into()); // Activate coldkey-swap guard for precompile dispatch account. let replacement_coldkey = AccountId::from([9u8; 32]);