Skip to content

Commit f6f547b

Browse files
authored
Merge pull request #1438 from opentensor/feat/stake-transfer-precompile
Feat/stake transfer precompile
2 parents 3cfc000 + 2d47812 commit f6f547b

File tree

5 files changed

+217
-21
lines changed

5 files changed

+217
-21
lines changed

precompiles/src/solidity/stakingV2.abi

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,5 +137,71 @@
137137
"outputs": [],
138138
"stateMutability": "nonpayable",
139139
"type": "function"
140+
},
141+
{
142+
"inputs": [
143+
{
144+
"internalType": "bytes32",
145+
"name": "origin_hotkey",
146+
"type": "bytes32"
147+
},
148+
{
149+
"internalType": "bytes32",
150+
"name": "destination_hotkey",
151+
"type": "bytes32"
152+
},
153+
{
154+
"internalType": "uint256",
155+
"name": "origin_netuid",
156+
"type": "uint256"
157+
},
158+
{
159+
"internalType": "uint256",
160+
"name": "destination_netuid",
161+
"type": "uint256"
162+
},
163+
{
164+
"internalType": "uint256",
165+
"name": "amount",
166+
"type": "uint256"
167+
}
168+
],
169+
"name": "moveStake",
170+
"outputs": [],
171+
"stateMutability": "nonpayable",
172+
"type": "function"
173+
},
174+
{
175+
"inputs": [
176+
{
177+
"internalType": "bytes32",
178+
"name": "destination_coldkey",
179+
"type": "bytes32"
180+
},
181+
{
182+
"internalType": "bytes32",
183+
"name": "hotkey",
184+
"type": "bytes32"
185+
},
186+
{
187+
"internalType": "uint256",
188+
"name": "origin_netuid",
189+
"type": "uint256"
190+
},
191+
{
192+
"internalType": "uint256",
193+
"name": "destination_netuid",
194+
"type": "uint256"
195+
},
196+
{
197+
"internalType": "uint256",
198+
"name": "amount",
199+
"type": "uint256"
200+
}
201+
],
202+
"name": "transferStake",
203+
"outputs": [],
204+
"stateMutability": "nonpayable",
205+
"type": "function"
140206
}
141207
]

precompiles/src/solidity/stakingV2.sol

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,62 @@ interface IStaking {
4646
uint256 netuid
4747
) external;
4848

49+
/**
50+
* @dev Moves a subtensor stake `amount` associated with the `hotkey` to a different hotkey
51+
* `destination_hotkey`.
52+
*
53+
* This function allows external accounts and contracts to move staked TAO from one hotkey to another,
54+
* which effectively calls `move_stake` on the subtensor pallet with specified origin and destination
55+
* hotkeys as parameters being the hashed address mappings of H160 sender address to Substrate ss58
56+
* address as implemented in Frontier HashedAddressMapping:
57+
* https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739
58+
*
59+
* @param origin_hotkey The origin hotkey public key (32 bytes).
60+
* @param destination_hotkey The destination hotkey public key (32 bytes).
61+
* @param origin_netuid The subnet to move stake from (uint256).
62+
* @param destination_netuid The subnet to move stake to (uint256).
63+
* @param amount The amount to move in rao.
64+
*
65+
* Requirements:
66+
* - `origin_hotkey` and `destination_hotkey` must be valid hotkeys registered on the network, ensuring
67+
* that the stake is correctly attributed.
68+
*/
69+
function moveStake(
70+
bytes32 origin_hotkey,
71+
bytes32 destination_hotkey,
72+
uint256 origin_netuid,
73+
uint256 destination_netuid,
74+
uint256 amount
75+
) external;
76+
77+
/**
78+
* @dev Transfer a subtensor stake `amount` associated with the transaction signer to a different coldkey
79+
* `destination_coldkey`.
80+
*
81+
* This function allows external accounts and contracts to transfer staked TAO to another coldkey,
82+
* which effectively calls `transfer_stake` on the subtensor pallet with specified destination
83+
* coldkey as a parameter being the hashed address mapping of H160 sender address to Substrate ss58
84+
* address as implemented in Frontier HashedAddressMapping:
85+
* https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739
86+
*
87+
* @param destination_coldkey The destination coldkey public key (32 bytes).
88+
* @param hotkey The hotkey public key (32 bytes).
89+
* @param origin_netuid The subnet to move stake from (uint256).
90+
* @param destination_netuid The subnet to move stake to (uint256).
91+
* @param amount The amount to move in rao.
92+
*
93+
* Requirements:
94+
* - `origin_hotkey` and `destination_hotkey` must be valid hotkeys registered on the network, ensuring
95+
* that the stake is correctly attributed.
96+
*/
97+
function transferStake(
98+
bytes32 destination_coldkey,
99+
bytes32 hotkey,
100+
uint256 origin_netuid,
101+
uint256 destination_netuid,
102+
uint256 amount
103+
) external;
104+
49105
/**
50106
* @dev Returns the amount of RAO staked by the coldkey.
51107
*

precompiles/src/solidity/subnet.abi

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,5 +883,23 @@
883883
"outputs": [],
884884
"stateMutability": "payable",
885885
"type": "function"
886+
},
887+
{
888+
"inputs": [
889+
{
890+
"internalType": "uint16",
891+
"name": "netuid",
892+
"type": "uint16"
893+
},
894+
{
895+
"internalType": "bool",
896+
"name": "toggle",
897+
"type": "bool"
898+
}
899+
],
900+
"name": "toggleTransfers",
901+
"outputs": [],
902+
"stateMutability": "payable",
903+
"type": "function"
886904
}
887905
]

precompiles/src/staking.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,58 @@ where
119119
handle.try_dispatch_runtime_call::<R, _>(call, RawOrigin::Signed(account_id))
120120
}
121121

122+
#[precompile::public("moveStake(bytes32,bytes32,uint256,uint256,uint256)")]
123+
fn move_stake(
124+
handle: &mut impl PrecompileHandle,
125+
origin_hotkey: H256,
126+
destination_hotkey: H256,
127+
origin_netuid: U256,
128+
destination_netuid: U256,
129+
amount_alpha: U256,
130+
) -> EvmResult<()> {
131+
let account_id = handle.caller_account_id::<R>();
132+
let origin_hotkey = R::AccountId::from(origin_hotkey.0);
133+
let destination_hotkey = R::AccountId::from(destination_hotkey.0);
134+
let origin_netuid = try_u16_from_u256(origin_netuid)?;
135+
let destination_netuid = try_u16_from_u256(destination_netuid)?;
136+
let alpha_amount = amount_alpha.unique_saturated_into();
137+
let call = pallet_subtensor::Call::<R>::move_stake {
138+
origin_hotkey,
139+
destination_hotkey,
140+
origin_netuid,
141+
destination_netuid,
142+
alpha_amount,
143+
};
144+
145+
handle.try_dispatch_runtime_call::<R, _>(call, RawOrigin::Signed(account_id))
146+
}
147+
148+
#[precompile::public("transferStake(bytes32,bytes32,uint256,uint256,uint256)")]
149+
fn transfer_stake(
150+
handle: &mut impl PrecompileHandle,
151+
destination_coldkey: H256,
152+
hotkey: H256,
153+
origin_netuid: U256,
154+
destination_netuid: U256,
155+
amount_alpha: U256,
156+
) -> EvmResult<()> {
157+
let account_id = handle.caller_account_id::<R>();
158+
let destination_coldkey = R::AccountId::from(destination_coldkey.0);
159+
let hotkey = R::AccountId::from(hotkey.0);
160+
let origin_netuid = try_u16_from_u256(origin_netuid)?;
161+
let destination_netuid = try_u16_from_u256(destination_netuid)?;
162+
let alpha_amount = amount_alpha.unique_saturated_into();
163+
let call = pallet_subtensor::Call::<R>::transfer_stake {
164+
destination_coldkey,
165+
hotkey,
166+
origin_netuid,
167+
destination_netuid,
168+
alpha_amount,
169+
};
170+
171+
handle.try_dispatch_runtime_call::<R, _>(call, RawOrigin::Signed(account_id))
172+
}
173+
122174
#[precompile::public("getTotalColdkeyStake(bytes32)")]
123175
#[precompile::view]
124176
fn get_total_coldkey_stake(

precompiles/src/subnet.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -200,19 +200,12 @@ where
200200
#[precompile::public("setWeightsSetRateLimit(uint16,uint64)")]
201201
#[precompile::payable]
202202
fn set_weights_set_rate_limit(
203-
handle: &mut impl PrecompileHandle,
204-
netuid: u16,
205-
weights_set_rate_limit: u64,
203+
_handle: &mut impl PrecompileHandle,
204+
_netuid: u16,
205+
_weights_set_rate_limit: u64,
206206
) -> EvmResult<()> {
207-
let call = pallet_admin_utils::Call::<R>::sudo_set_weights_set_rate_limit {
208-
netuid,
209-
weights_set_rate_limit,
210-
};
211-
212-
handle.try_dispatch_runtime_call::<R, _>(
213-
call,
214-
RawOrigin::Signed(handle.caller_account_id::<R>()),
215-
)
207+
// DEPRECATED. Subnet owner cannot set weight setting rate limits
208+
Ok(())
216209
}
217210

218211
#[precompile::public("getAdjustmentAlpha(uint16)")]
@@ -436,16 +429,12 @@ where
436429
#[precompile::public("setMinBurn(uint16,uint64)")]
437430
#[precompile::payable]
438431
fn set_min_burn(
439-
handle: &mut impl PrecompileHandle,
440-
netuid: u16,
441-
min_burn: u64,
432+
_handle: &mut impl PrecompileHandle,
433+
_netuid: u16,
434+
_min_burn: u64,
442435
) -> EvmResult<()> {
443-
let call = pallet_admin_utils::Call::<R>::sudo_set_min_burn { netuid, min_burn };
444-
445-
handle.try_dispatch_runtime_call::<R, _>(
446-
call,
447-
RawOrigin::Signed(handle.caller_account_id::<R>()),
448-
)
436+
// DEPRECATED. The subnet owner cannot set the min burn anymore.
437+
Ok(())
449438
}
450439

451440
#[precompile::public("getMaxBurn(uint16)")]
@@ -616,4 +605,19 @@ where
616605
RawOrigin::Signed(handle.caller_account_id::<R>()),
617606
)
618607
}
608+
609+
#[precompile::public("toggleTransfers(uint16,bool)")]
610+
#[precompile::payable]
611+
fn toggle_transfers(
612+
handle: &mut impl PrecompileHandle,
613+
netuid: u16,
614+
toggle: bool,
615+
) -> EvmResult<()> {
616+
let call = pallet_admin_utils::Call::<R>::sudo_set_toggle_transfer { netuid, toggle };
617+
618+
handle.try_dispatch_runtime_call::<R, _>(
619+
call,
620+
RawOrigin::Signed(handle.caller_account_id::<R>()),
621+
)
622+
}
619623
}

0 commit comments

Comments
 (0)