Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions evm-tests/src/contracts/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,24 @@ export const IProxyABI = [
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "account",
"type": "bytes32"
}
],
"name": "getProxies",
"outputs": [
{
"internalType": "bytes32[]",
"name": "",
"type": "bytes32[]"
}
],
"stateMutability": "view",
"type": "function"
}
];
50 changes: 42 additions & 8 deletions evm-tests/test/pure-proxy.precompile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,34 +130,68 @@ describe("Test pure proxy precompile", () => {
const proxies = await api.query.Proxy.Proxies.getValue(convertH160ToSS58(evmWallet2.address))
const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet2)

const proxiesFromContract = await contract.getProxies(convertH160ToPublicKey(evmWallet2.address))
assert.equal(proxiesFromContract.length, proxies[0].length, "proxies length should be equal")

const type = 0;
const delay = 0;

const tx = await contract.addProxy(convertH160ToPublicKey(evmWallet3.address), type, delay)
await tx.wait()


const proxiesAfterAdd = await await api.query.Proxy.Proxies.getValue(convertH160ToSS58(evmWallet2.address))
const proxiesList = proxiesAfterAdd[0].map(proxy => proxy.delegate)
const proxiesFromContractAfterAdd = await contract.getProxies(convertH160ToPublicKey(evmWallet2.address))
assert.equal(proxiesFromContractAfterAdd.length, proxiesList.length, "proxy length should be equal")

const length = proxiesAfterAdd[0].length
assert.equal(length, proxies[0].length + 1, "proxy should be set")
const proxy = proxiesAfterAdd[0][proxiesAfterAdd[0].length - 1]

assert.equal(proxy.delegate, convertH160ToSS58(evmWallet3.address), "proxy should be set")
for (let index = 0; index < proxiesFromContractAfterAdd.length; index++) {
let proxySs58 = convertPublicKeyToSs58(proxiesFromContractAfterAdd[index])
assert.ok(proxiesList.includes(proxySs58), "proxy should be set")
}

assert.equal(proxiesList.length, proxies[0].length + 1, "proxy should be set")
const proxy = proxiesList[proxiesList.length - 1]

assert.equal(proxy, convertH160ToSS58(evmWallet3.address), "proxy should be set")
const balance = (await api.query.System.Account.getValue(convertPublicKeyToSs58(receiver.publicKey))).data.free

const amount = 1000000000;

const contract2 = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet3)


const callCode = await getTransferCallCode(api, receiver, amount)
const tx2 = await contract2.proxyCall(convertH160ToPublicKey(evmWallet2.address), [type], callCode)
await tx2.wait()

const balanceAfter = (await api.query.System.Account.getValue(convertPublicKeyToSs58(receiver.publicKey))).data.free
assert.equal(balanceAfter, balance + BigInt(amount), "balance should be increased")
})

it("Call addProxy many times, then check getProxies is correct", async () => {
const proxies = await api.query.Proxy.Proxies.getValue(convertH160ToSS58(evmWallet2.address))
const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet2)

const proxiesFromContract = await contract.getProxies(convertH160ToPublicKey(evmWallet2.address))
assert.equal(proxiesFromContract.length, proxies[0].length, "proxies length should be equal")

const type = 0;
const delay = 0;

for (let i = 0; i < 5; i++) {
const evmWallet = generateRandomEthersWallet()
const tx = await contract.addProxy(convertH160ToPublicKey(evmWallet.address), type, delay)
await tx.wait()
}

const proxiesAfterAdd = await await api.query.Proxy.Proxies.getValue(convertH160ToSS58(evmWallet2.address))
const proxiesList = proxiesAfterAdd[0].map(proxy => proxy.delegate)

const proxiesFromContractAfterAdd = await contract.getProxies(convertH160ToPublicKey(evmWallet2.address))

assert.equal(proxiesFromContractAfterAdd.length, proxiesList.length, "proxy length should be equal")

for (let index = 0; index < proxiesFromContractAfterAdd.length; index++) {
let proxySs58 = convertPublicKeyToSs58(proxiesFromContractAfterAdd[index])
assert.ok(proxiesList.includes(proxySs58), "proxy should be set")
}
})
});
19 changes: 19 additions & 0 deletions precompiles/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use sp_runtime::{
traits::{Dispatchable, StaticLookup},
};
use sp_std::boxed::Box;
use sp_std::vec;
use sp_std::vec::Vec;
use subtensor_runtime_common::ProxyType;
pub struct ProxyPrecompile<R>(PhantomData<R>);
Expand Down Expand Up @@ -239,4 +240,22 @@ where

handle.try_dispatch_runtime_call::<R, _>(call, RawOrigin::Signed(account_id))
}

#[precompile::public("getProxies(bytes32)")]
#[precompile::view]
pub fn get_proxies(
_handle: &mut impl PrecompileHandle,
account_id: H256,
) -> EvmResult<Vec<H256>> {
let account_id = R::AccountId::from(account_id.0.into());

let proxies = pallet_proxy::pallet::Pallet::<R>::proxies(account_id);
let mut result: Vec<H256> = vec![];
for proxy in proxies.0 {
let delegate: [u8; 32] = proxy.delegate.into();
result.push(delegate.into());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add the proxytype and the delay here
Returning a struct would be nice

}

Ok(result)
}
}
160 changes: 160 additions & 0 deletions precompiles/src/solidity/proxy.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
[
{
"type": "function",
"name": "createPureProxy",
"inputs": [
{
"name": "proxy_type",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "delay",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "index",
"type": "uint16",
"internalType": "uint16"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "proxyCall",
"inputs": [
{
"name": "real",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "force_proxy_type",
"type": "uint8[]",
"internalType": "uint8[]"
},
{
"name": "call",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "killPureProxy",
"inputs": [
{
"name": "spawner",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "proxy_type",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "index",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "height",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "ext_index",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "addProxy",
"inputs": [
{
"name": "delegate",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "proxy_type",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "delay",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "removeProxy",
"inputs": [
{
"name": "delegate",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "proxy_type",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "delay",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "removeProxies",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "pokeDeposit",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "getProxies",
"inputs": [
{
"name": "account",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "bytes32[]",
"internalType": "bytes32[]"
}
],
"stateMutability": "view"
}
]
38 changes: 27 additions & 11 deletions precompiles/src/solidity/proxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,42 @@ address constant IPROXY_ADDRESS = 0x000000000000000000000000000000000000080b;

interface IProxy {
function createPureProxy(
uint8 proxy_type,
uint32 delay,
uint16 index
uint8 proxy_type,
uint32 delay,
uint16 index
) external;

function proxyCall(bytes32 real, uint8[] memory force_proxy_type, bytes memory call) external;
function proxyCall(
bytes32 real,
uint8[] memory force_proxy_type,
bytes memory call
) external;

function killPureProxy(
bytes32 spawner,
uint8 proxy_type,
uint16 index,
uint16 height,
uint32 ext_index
bytes32 spawner,
uint8 proxy_type,
uint16 index,
uint16 height,
uint32 ext_index
) external;

function addProxy(bytes32 delegate, uint8 proxy_type, uint32 delay) external;
function addProxy(
bytes32 delegate,
uint8 proxy_type,
uint32 delay
) external;

function removeProxy(bytes32 delegate, uint8 proxy_type, uint32 delay) external;
function removeProxy(
bytes32 delegate,
uint8 proxy_type,
uint32 delay
) external;

function removeProxies() external;

function pokeDeposit() external;

function getProxies(
bytes32 account
) external view returns (bytes32[] memory);
}
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 346,
spec_version: 347,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading