From 6b6431e1af77acbc3d4b6cf29edcff852db595cf Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 12 Nov 2024 18:02:12 +0800 Subject: [PATCH 01/11] get stake interface in solidity --- runtime/src/precompiles/solidity/staking.abi | 28 ++++++++++++++++++-- runtime/src/precompiles/solidity/staking.sol | 12 +++++++++ runtime/src/precompiles/staking.rs | 15 +++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi index 44b1829c40..f20d7c338b 100644 --- a/runtime/src/precompiles/solidity/staking.abi +++ b/runtime/src/precompiles/solidity/staking.abi @@ -17,6 +17,30 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -37,7 +61,7 @@ ], "name": "removeStake", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" } -] +] \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/staking.sol b/runtime/src/precompiles/solidity/staking.sol index ec7fb72974..e0a8676385 100644 --- a/runtime/src/precompiles/solidity/staking.sol +++ b/runtime/src/precompiles/solidity/staking.sol @@ -42,4 +42,16 @@ interface IStaking { * - The existing stake amount must be not lower than specified amount */ function removeStake(bytes32 hotkey, uint256 amount, uint16 netuid) external; + + /** + * @dev Returns the stake amount associated with the specified `hotkey` and `coldkey`. + * + * This function retrieves the current stake amount linked to a specific hotkey and coldkey pair. + * It is a view function, meaning it does not modify the state of the contract and is free to call. + * + * @param hotkey The hotkey public key (32 bytes). + * @param coldkey The coldkey public key (32 bytes). + * @return The current stake amount in uint64 format. + */ + function getStake(bytes32 hotkey, bytes32 coldkey) external view returns (uint64); } diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index e6237dfcfa..104bb21160 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -59,6 +59,9 @@ impl StakingPrecompile { id if id == get_method_id("removeStake(bytes32,uint256,uint16)") => { Self::remove_stake(handle, &method_input) } + id if id == get_method_id("getStake(bytes32,bytes32)") => { + Self::get_stake(handle, &method_input) + } _ => Err(PrecompileFailure::Error { exit_status: ExitError::InvalidRange, }), @@ -101,6 +104,18 @@ impl StakingPrecompile { Self::dispatch(handle, call) } + fn get_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { + let hotkey: AccountId32 = Self::parse_hotkey(data)?.into(); + + let data = + pallet_subtensor::Pallet::::get_stake_for_coldkey_and_hotkey(&hotkey, &hotkey); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: data.to_le_bytes().to_vec(), + }) + } + fn parse_hotkey(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> { if data.len() < 32 { return Err(PrecompileFailure::Error { From 9688e037061a66b0bfdb507081c71f76e912fd6a Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 12 Nov 2024 21:59:14 +0800 Subject: [PATCH 02/11] parse keys for stake map --- runtime/src/precompiles/staking.rs | 31 ++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index 104bb21160..0190db413c 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -60,7 +60,7 @@ impl StakingPrecompile { Self::remove_stake(handle, &method_input) } id if id == get_method_id("getStake(bytes32,bytes32)") => { - Self::get_stake(handle, &method_input) + Self::get_stake(&method_input) } _ => Err(PrecompileFailure::Error { exit_status: ExitError::InvalidRange, @@ -104,18 +104,37 @@ impl StakingPrecompile { Self::dispatch(handle, call) } - fn get_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let hotkey: AccountId32 = Self::parse_hotkey(data)?.into(); + fn get_stake(data: &[u8]) -> PrecompileResult { + let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?.into(); - let data = - pallet_subtensor::Pallet::::get_stake_for_coldkey_and_hotkey(&hotkey, &hotkey); + let stake = pallet_subtensor::Pallet::::get_stake_for_coldkey_and_hotkey( + &hotkey.into(), + &coldkey.into(), + ); + + let stake_u256 = U256::from(stake); + let mut result = [0_u8; 32]; + U256::to_big_endian(&stake_u256, &mut result); Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - output: data.to_le_bytes().to_vec(), + output: result.into(), }) } + fn parse_hotkey_coldkey(data: &[u8]) -> Result<([u8; 32], [u8; 32]), PrecompileFailure> { + if data.len() < 64 { + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut hotkey = [0u8; 32]; + hotkey.copy_from_slice(get_slice(data, 0, 32)?); + let mut coldkey = [0u8; 32]; + coldkey.copy_from_slice(get_slice(data, 32, 64)?); + Ok((hotkey, coldkey)) + } + fn parse_hotkey(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> { if data.len() < 32 { return Err(PrecompileFailure::Error { From 9f64385ff2e518e2ef5a34da733e9741a4c4a57c Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 13 Nov 2024 13:24:42 +0800 Subject: [PATCH 03/11] fix clippy --- runtime/src/precompiles/staking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index 0190db413c..3af0e3e5e3 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -105,7 +105,7 @@ impl StakingPrecompile { } fn get_stake(data: &[u8]) -> PrecompileResult { - let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?.into(); + let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?; let stake = pallet_subtensor::Pallet::::get_stake_for_coldkey_and_hotkey( &hotkey.into(), From 8647528c8ff61601d9ab0ee94958fd9f4dd1c0e3 Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 13 Nov 2024 16:51:11 +0800 Subject: [PATCH 04/11] revert payable attribute --- runtime/src/precompiles/solidity/staking.abi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi index f20d7c338b..167c218824 100644 --- a/runtime/src/precompiles/solidity/staking.abi +++ b/runtime/src/precompiles/solidity/staking.abi @@ -61,7 +61,7 @@ ], "name": "removeStake", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" } ] \ No newline at end of file From 5a5f7e22670a934e374163c2bf4b6a5be02be016 Mon Sep 17 00:00:00 2001 From: gztensor <166415444+gztensor@users.noreply.github.com> Date: Tue, 14 Jan 2025 07:50:44 -0800 Subject: [PATCH 05/11] Update runtime/src/precompiles/solidity/staking.sol Co-authored-by: Cameron Fairchild --- runtime/src/precompiles/solidity/staking.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/precompiles/solidity/staking.sol b/runtime/src/precompiles/solidity/staking.sol index e0a8676385..f252727ca3 100644 --- a/runtime/src/precompiles/solidity/staking.sol +++ b/runtime/src/precompiles/solidity/staking.sol @@ -53,5 +53,5 @@ interface IStaking { * @param coldkey The coldkey public key (32 bytes). * @return The current stake amount in uint64 format. */ - function getStake(bytes32 hotkey, bytes32 coldkey) external view returns (uint64); + function getStake(bytes32 hotkey, bytes32 coldkey, uint16 netuid) external view returns (uint64); } From fd8fd5315d188cb3268344f0eb4450e0697b320e Mon Sep 17 00:00:00 2001 From: gztensor <166415444+gztensor@users.noreply.github.com> Date: Tue, 14 Jan 2025 07:50:55 -0800 Subject: [PATCH 06/11] Update runtime/src/precompiles/solidity/staking.sol Co-authored-by: Cameron Fairchild --- runtime/src/precompiles/solidity/staking.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/src/precompiles/solidity/staking.sol b/runtime/src/precompiles/solidity/staking.sol index f252727ca3..4416106937 100644 --- a/runtime/src/precompiles/solidity/staking.sol +++ b/runtime/src/precompiles/solidity/staking.sol @@ -51,6 +51,7 @@ interface IStaking { * * @param hotkey The hotkey public key (32 bytes). * @param coldkey The coldkey public key (32 bytes). + * @param netuid The subnet the stake is on (uint16). * @return The current stake amount in uint64 format. */ function getStake(bytes32 hotkey, bytes32 coldkey, uint16 netuid) external view returns (uint64); From 0b30f3b82e64e2a2c6065f31ffffc51ec98aedfa Mon Sep 17 00:00:00 2001 From: gztensor <166415444+gztensor@users.noreply.github.com> Date: Tue, 14 Jan 2025 07:51:04 -0800 Subject: [PATCH 07/11] Update runtime/src/precompiles/staking.rs Co-authored-by: Cameron Fairchild --- runtime/src/precompiles/staking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index 748f1078a7..6f38afbdbf 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -59,7 +59,7 @@ impl StakingPrecompile { id if id == get_method_id("removeStake(bytes32,uint256,uint16)") => { Self::remove_stake(handle, &method_input) } - id if id == get_method_id("getStake(bytes32,bytes32)") => { + id if id == get_method_id("getStake(bytes32,bytes32,uint16)") => { Self::get_stake(&method_input) } _ => Err(PrecompileFailure::Error { From 9d3218b418595356cde86a42f69a82f130753eea Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 14 Jan 2025 12:16:50 -0500 Subject: [PATCH 08/11] Add netuid to get_stake in staking precompile --- runtime/src/precompiles/staking.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index 6f38afbdbf..9d48501d4f 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -115,10 +115,12 @@ impl StakingPrecompile { fn get_stake(data: &[u8]) -> PrecompileResult { let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?; + let netuid = Self::parse_netuid(data, 0x3E)?; - let stake = pallet_subtensor::Pallet::::get_stake_for_coldkey_and_hotkey( + let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey.into(), &coldkey.into(), + netuid, ); let stake_u256 = U256::from(stake); From 14093cc50ec0d1efb7d89cb06f188d4591be5393 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 14 Jan 2025 12:31:26 -0500 Subject: [PATCH 09/11] Add netuid to get_stake ABI --- runtime/src/precompiles/solidity/staking.abi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi index 1332718ad3..52e07b3ba5 100644 --- a/runtime/src/precompiles/solidity/staking.abi +++ b/runtime/src/precompiles/solidity/staking.abi @@ -52,6 +52,11 @@ "internalType": "bytes32", "name": "coldkey", "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "netuid", + "type": "uint256" } ], "name": "getStake", From af7a5417a84d9be93e53ca7fdc74b5361e3e9912 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 14 Jan 2025 12:37:23 -0500 Subject: [PATCH 10/11] Fix staking precompile ABI --- runtime/src/precompiles/solidity/staking.abi | 24 -------------------- 1 file changed, 24 deletions(-) diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi index 52e07b3ba5..c5c6bb38ba 100644 --- a/runtime/src/precompiles/solidity/staking.abi +++ b/runtime/src/precompiles/solidity/staking.abi @@ -17,30 +17,6 @@ "stateMutability": "payable", "type": "function" }, - { - inputs: [ - { - internalType: "bytes32", - name: "hotkey", - type: "bytes32", - }, - { - internalType: "bytes32", - name: "coldkey", - type: "bytes32", - }, - ], - name: "getStake", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, { "inputs": [ { From f4ffb5ca2f534b5913c045d6fe41748429d8e2fb Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 14 Jan 2025 13:27:49 -0500 Subject: [PATCH 11/11] Fix get_stake in staking precompile --- runtime/src/precompiles/solidity/staking.abi | 4 ++-- runtime/src/precompiles/solidity/staking.sol | 4 ++-- runtime/src/precompiles/staking.rs | 12 +++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi index c5c6bb38ba..82583543dd 100644 --- a/runtime/src/precompiles/solidity/staking.abi +++ b/runtime/src/precompiles/solidity/staking.abi @@ -38,9 +38,9 @@ "name": "getStake", "outputs": [ { - "internalType": "uint64", + "internalType": "uint256", "name": "", - "type": "uint64" + "type": "uint256" } ], "stateMutability": "view", diff --git a/runtime/src/precompiles/solidity/staking.sol b/runtime/src/precompiles/solidity/staking.sol index c7efe5a8a5..7c80d53e0e 100644 --- a/runtime/src/precompiles/solidity/staking.sol +++ b/runtime/src/precompiles/solidity/staking.sol @@ -51,7 +51,7 @@ interface IStaking { * @param hotkey The hotkey public key (32 bytes). * @param coldkey The coldkey public key (32 bytes). * @param netuid The subnet the stake is on (uint256). - * @return The current stake amount in uint64 format. + * @return The current stake amount in uint256 format. */ - function getStake(bytes32 hotkey, bytes32 coldkey, uint256 netuid) external view returns (uint64); + function getStake(bytes32 hotkey, bytes32 coldkey, uint256 netuid) external view returns (uint256); } diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index f4439b8a97..bee4b30d1b 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -59,7 +59,7 @@ impl StakingPrecompile { id if id == get_method_id("removeStake(bytes32,uint256,uint256)") => { Self::remove_stake(handle, &method_input) } - id if id == get_method_id("getStake(bytes32,bytes32,uint16)") => { + id if id == get_method_id("getStake(bytes32,bytes32,uint256)") => { Self::get_stake(&method_input) } _ => Err(PrecompileFailure::Error { @@ -112,7 +112,7 @@ impl StakingPrecompile { fn get_stake(data: &[u8]) -> PrecompileResult { let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?; - let netuid = Self::parse_netuid(data, 0x3E)?; + let netuid = Self::parse_netuid(data, 0x5E)?; let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey.into(), @@ -120,9 +120,15 @@ impl StakingPrecompile { netuid, ); + // Convert to EVM decimals let stake_u256 = U256::from(stake); + let stake_eth = + ::BalanceConverter::into_evm_balance(stake_u256) + .ok_or(ExitError::InvalidRange)?; + + // Format output let mut result = [0_u8; 32]; - U256::to_big_endian(&stake_u256, &mut result); + U256::to_big_endian(&stake_eth, &mut result); Ok(PrecompileOutput { exit_status: ExitSucceed::Returned,