diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi index 44b1829c4..167c21882 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": [ { @@ -40,4 +64,4 @@ "stateMutability": "payable", "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 ec7fb7297..e0a867638 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 bf930005b..748f1078a 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(&method_input) + } _ => Err(PrecompileFailure::Error { exit_status: ExitError::InvalidRange, }), @@ -110,6 +113,37 @@ impl StakingPrecompile { Self::dispatch(handle, call) } + fn get_stake(data: &[u8]) -> PrecompileResult { + let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?; + + 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: 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 {