Skip to content

Commit 3e31bb9

Browse files
committed
Add Validate proxy type and validator flow tests
1 parent 3708f42 commit 3e31bb9

7 files changed

Lines changed: 651 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub enum ProxyType {
165165
SwapHotkey,
166166
SubnetLeaseBeneficiary, // Used to operate the leased subnet
167167
RootClaim,
168+
Validate,
168169
}
169170

170171
impl TryFrom<u8> for ProxyType {
@@ -190,6 +191,7 @@ impl TryFrom<u8> for ProxyType {
190191
15 => Ok(Self::SwapHotkey),
191192
16 => Ok(Self::SubnetLeaseBeneficiary),
192193
17 => Ok(Self::RootClaim),
194+
18 => Ok(Self::Validate),
193195
_ => Err(()),
194196
}
195197
}
@@ -216,6 +218,7 @@ impl From<ProxyType> for u8 {
216218
ProxyType::SwapHotkey => 15,
217219
ProxyType::SubnetLeaseBeneficiary => 16,
218220
ProxyType::RootClaim => 17,
221+
ProxyType::Validate => 18,
219222
}
220223
}
221224
}
@@ -453,4 +456,34 @@ mod tests {
453456
fn netuid_has_u16_bin_repr() {
454457
assert_eq!(NetUid(5).encode(), 5u16.encode());
455458
}
459+
460+
#[test]
461+
fn proxy_type_ids_remain_stable_and_validate_roundtrips() {
462+
let expected_ids = [
463+
(ProxyType::Any, 0u8),
464+
(ProxyType::Owner, 1u8),
465+
(ProxyType::NonCritical, 2u8),
466+
(ProxyType::NonTransfer, 3u8),
467+
(ProxyType::Senate, 4u8),
468+
(ProxyType::NonFungible, 5u8),
469+
(ProxyType::Triumvirate, 6u8),
470+
(ProxyType::Governance, 7u8),
471+
(ProxyType::Staking, 8u8),
472+
(ProxyType::Registration, 9u8),
473+
(ProxyType::Transfer, 10u8),
474+
(ProxyType::SmallTransfer, 11u8),
475+
(ProxyType::RootWeights, 12u8),
476+
(ProxyType::ChildKeys, 13u8),
477+
(ProxyType::SudoUncheckedSetCode, 14u8),
478+
(ProxyType::SwapHotkey, 15u8),
479+
(ProxyType::SubnetLeaseBeneficiary, 16u8),
480+
(ProxyType::RootClaim, 17u8),
481+
(ProxyType::Validate, 18u8),
482+
];
483+
484+
for (proxy_type, id) in expected_ids {
485+
assert_eq!(<u8 as From<ProxyType>>::from(proxy_type), id);
486+
assert_eq!(ProxyType::try_from(id), Ok(proxy_type));
487+
}
488+
}
456489
}

contract-tests/test/pure-proxy.precompile.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ async function getTransferCallCode(api: TypedApi<typeof devnet>, receiver: KeyPa
2828
return [...data]
2929
}
3030

31+
async function getRemarkCallCode(api: TypedApi<typeof devnet>) {
32+
const unsignedTx = api.tx.System.remark({ remark: new Uint8Array([1, 2, 3]) });
33+
const encodedCallDataBytes = await unsignedTx.getEncodedData();
34+
return [...encodedCallDataBytes.asBytes()];
35+
}
36+
3137
async function getProxies(api: TypedApi<typeof devnet>, address: string) {
3238
const entries = await api.query.Proxy.Proxies.getEntries()
3339
const result = []
@@ -207,4 +213,43 @@ describe("Test pure proxy precompile", () => {
207213
assert.equal(Number(proxyInfo[2]), delay, "delay should match")
208214
}
209215
})
216+
217+
it("Call createPureProxy with Validate type", async () => {
218+
const validateType = 18;
219+
const validateWallet = generateRandomEthersWallet();
220+
await forceSetBalanceToEthAddress(api, validateWallet.address);
221+
222+
const proxiesBefore = await getProxies(api, convertH160ToSS58(validateWallet.address));
223+
const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, validateWallet);
224+
225+
const tx = await contract.createPureProxy(validateType, 0, 0);
226+
await tx.wait();
227+
228+
const proxiesAfter = await getProxies(api, convertH160ToSS58(validateWallet.address));
229+
assert.equal(proxiesAfter.length, proxiesBefore.length + 1, "validate pure proxy should be created");
230+
})
231+
232+
it("Call addProxy with Validate type, then reject non-Validate call", async () => {
233+
const validateType = 18;
234+
const ownerWallet = generateRandomEthersWallet();
235+
const delegateWallet = generateRandomEthersWallet();
236+
await forceSetBalanceToEthAddress(api, ownerWallet.address);
237+
await forceSetBalanceToEthAddress(api, delegateWallet.address);
238+
239+
const ownerContract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, ownerWallet);
240+
const addProxyTx = await ownerContract.addProxy(convertH160ToPublicKey(delegateWallet.address), validateType, 0);
241+
await addProxyTx.wait();
242+
243+
const delegateContract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, delegateWallet);
244+
const remarkCall = await getRemarkCallCode(api);
245+
246+
await assert.rejects(
247+
async () => {
248+
const tx = await delegateContract.proxyCall(convertH160ToPublicKey(ownerWallet.address), [validateType], remarkCall);
249+
await tx.wait();
250+
},
251+
undefined,
252+
"validate proxy should reject a remark call"
253+
);
254+
})
210255
});

pallets/subtensor/src/utils/evm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use subtensor_runtime_common::NetUid;
1010
const MESSAGE_PREFIX: &str = "\x19Ethereum Signed Message:\n";
1111

1212
impl<T: Config> Pallet<T> {
13-
pub(crate) fn hash_message_eip191<M: AsRef<[u8]>>(message: M) -> [u8; 32] {
13+
pub fn hash_message_eip191<M: AsRef<[u8]>>(message: M) -> [u8; 32] {
1414
let msg_len = message.as_ref().len().to_string();
1515
keccak_256(
1616
&[

runtime/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ ethereum.workspace = true
158158

159159
[dev-dependencies]
160160
frame-metadata.workspace = true
161+
libsecp256k1.workspace = true
161162
sp-io.workspace = true
162163
sp-tracing.workspace = true
163164
precompile-utils = { workspace = true, features = ["testing"] }
@@ -280,6 +281,7 @@ std = [
280281
"pallet-shield/std",
281282
"stp-shield/std",
282283
"sp-weights/std",
284+
"libsecp256k1/std",
283285
]
284286
runtime-benchmarks = [
285287
"frame-benchmarking/runtime-benchmarks",

runtime/src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,34 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
810810
c,
811811
RuntimeCall::SubtensorModule(pallet_subtensor::Call::claim_root { .. })
812812
),
813+
ProxyType::Validate => {
814+
matches!(
815+
c,
816+
RuntimeCall::SubtensorModule(
817+
pallet_subtensor::Call::serve_axon { .. }
818+
| pallet_subtensor::Call::serve_axon_tls { .. }
819+
| pallet_subtensor::Call::associate_evm_key { .. }
820+
| pallet_subtensor::Call::set_weights { .. }
821+
| pallet_subtensor::Call::set_mechanism_weights { .. }
822+
| pallet_subtensor::Call::batch_set_weights { .. }
823+
| pallet_subtensor::Call::commit_weights { .. }
824+
| pallet_subtensor::Call::commit_mechanism_weights { .. }
825+
| pallet_subtensor::Call::batch_commit_weights { .. }
826+
| pallet_subtensor::Call::reveal_weights { .. }
827+
| pallet_subtensor::Call::reveal_mechanism_weights { .. }
828+
| pallet_subtensor::Call::batch_reveal_weights { .. }
829+
| pallet_subtensor::Call::commit_timelocked_weights { .. }
830+
| pallet_subtensor::Call::commit_crv3_mechanism_weights { .. }
831+
| pallet_subtensor::Call::commit_timelocked_mechanism_weights { .. }
832+
) | RuntimeCall::Commitments(pallet_commitments::Call::set_commitment { .. })
833+
) || matches!(
834+
c,
835+
RuntimeCall::Proxy(pallet_subtensor_proxy::Call::add_proxy {
836+
proxy_type: ProxyType::Validate,
837+
..
838+
})
839+
)
840+
}
813841
}
814842
}
815843
fn is_superset(&self, o: &Self) -> bool {

0 commit comments

Comments
 (0)