From 3fe135890f7559c08b48fec7355afd261d81a2ba Mon Sep 17 00:00:00 2001 From: 4meta5 Date: Tue, 13 Dec 2022 21:32:13 -0500 Subject: [PATCH 1/8] staking delegation amount getter and is in top delegations --- .../parachain-staking/StakingInterface.sol | 20 +++ precompiles/parachain-staking/src/lib.rs | 77 +++++++++++ precompiles/parachain-staking/src/mock.rs | 2 +- precompiles/parachain-staking/src/tests.rs | 124 ++++++++++++++++++ 4 files changed, 222 insertions(+), 1 deletion(-) diff --git a/precompiles/parachain-staking/StakingInterface.sol b/precompiles/parachain-staking/StakingInterface.sol index 218d98ebf6..23fb2a5439 100644 --- a/precompiles/parachain-staking/StakingInterface.sol +++ b/precompiles/parachain-staking/StakingInterface.sol @@ -43,6 +43,26 @@ interface ParachainStaking { /// @return The total points awarded to all collators in the round function points(uint256 round) external view returns (uint256); + /// @dev The amount delegated in support of the candidate by the delegator + /// @custom:selector a73e51bc + /// @param candidate The candidate for which the delegation is in support of + /// @param delegator Who made this delegation + /// @return The amount of the delegation in support of the candidate by the delegator + function delegationAmount(address candidate, address delegator) + external + view + returns (uint256); + + /// @dev Whether the delegation is in the top delegations + /// @custom:selector 91cc8657 + /// @param candidate The candidate for which the delegation is in support of + /// @param delegator Who made this delegation + /// @return If delegation is in top delegations (is counted) + function isInTopDelegations(address candidate, address delegator) + external + view + returns (bool); + /// @dev Get the minimum delegation amount /// @custom:selector 02985992 /// @return The minimum delegation amount diff --git a/precompiles/parachain-staking/src/lib.rs b/precompiles/parachain-staking/src/lib.rs index 9718be9d9c..506ac126f5 100644 --- a/precompiles/parachain-staking/src/lib.rs +++ b/precompiles/parachain-staking/src/lib.rs @@ -196,7 +196,84 @@ where Ok(selected_candidates) } + #[precompile::public("delegationAmount(address,address)")] + #[precompile::view] + fn delegation_amount( + handle: &mut impl PrecompileHandle, + candidate: Address, + delegator: Address, + ) -> EvmResult { + // Fetch info. + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let (candidate, delegator) = ( + Runtime::AddressMapping::into_account_id(candidate.0), + Runtime::AddressMapping::into_account_id(delegator.0), + ); + let amount: U256 = if let Some(state) = + pallet_parachain_staking::Pallet::::delegator_state(&delegator) + { + // get the delegation amount + if let Some(pallet_parachain_staking::Bond { amount, .. }) = state + .delegations + .0 + .into_iter() + .find(|b| b.owner == candidate) + { + amount.into() + } else { + log::trace!( + target: "staking-precompile", + "Delegation for {:?} not found, so delegation amount is 0", + candidate + ); + U256::zero() + } + } else { + log::trace!( + target: "staking-precompile", + "Delegator state for {:?} not found, so delegation amount is 0", + delegator + ); + U256::zero() + }; + + Ok(amount) + } + // Role Verifiers + #[precompile::public("isInTopDelegations(address,address)")] + #[precompile::view] + fn is_in_top_delegations( + handle: &mut impl PrecompileHandle, + candidate: Address, + delegator: Address, + ) -> EvmResult { + let (candidate, delegator) = ( + Runtime::AddressMapping::into_account_id(candidate.0), + Runtime::AddressMapping::into_account_id(delegator.0), + ); + + // Fetch info. + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let is_in_top_delegations = if let Some(delegations) = + pallet_parachain_staking::Pallet::::top_delegations(&candidate) + { + delegations + .delegations + .into_iter() + .any(|b| b.owner == delegator) + } else { + log::trace!( + target: "staking-precompile", + "Candidate state for {:?} not found, so delegation is not in top", + candidate + ); + false + }; + + Ok(is_in_top_delegations) + } + #[precompile::public("isDelegator(address)")] #[precompile::public("is_delegator(address)")] #[precompile::view] diff --git a/precompiles/parachain-staking/src/mock.rs b/precompiles/parachain-staking/src/mock.rs index fd6c600196..218704e493 100644 --- a/precompiles/parachain-staking/src/mock.rs +++ b/precompiles/parachain-staking/src/mock.rs @@ -154,7 +154,7 @@ parameter_types! { pub const DelegationBondLessDelay: u32 = 2; pub const RewardPaymentDelay: u32 = 2; pub const MinSelectedCandidates: u32 = 5; - pub const MaxTopDelegationsPerCandidate: u32 = 4; + pub const MaxTopDelegationsPerCandidate: u32 = 2; pub const MaxBottomDelegationsPerCandidate: u32 = 4; pub const MaxDelegationsPerDelegator: u32 = 4; pub const DefaultCollatorCommission: Perbill = Perbill::from_percent(20); diff --git a/precompiles/parachain-staking/src/tests.rs b/precompiles/parachain-staking/src/tests.rs index 25775e3a0b..278ef7aee5 100644 --- a/precompiles/parachain-staking/src/tests.rs +++ b/precompiles/parachain-staking/src/tests.rs @@ -49,6 +49,8 @@ fn selectors() { assert!(PCall::is_delegator_selectors().contains(&0xfd8ab482)); assert!(PCall::is_candidate_selectors().contains(&0xd51b9e93)); assert!(PCall::is_selected_candidate_selectors().contains(&0x740d7d2a)); + assert!(PCall::delegation_amount_selectors().contains(&0xa73e51bc)); + assert!(PCall::is_in_top_delegations_selectors().contains(&0x91cc8657)); assert!(PCall::points_selectors().contains(&0x9799b4e7)); assert!(PCall::min_delegation_selectors().contains(&0x02985992)); assert!(PCall::candidate_count_selectors().contains(&0xa9a981a3)); @@ -89,6 +91,8 @@ fn modifiers() { tester.test_view_modifier(PCall::is_candidate_selectors()); tester.test_view_modifier(PCall::is_selected_candidate_selectors()); tester.test_view_modifier(PCall::points_selectors()); + tester.test_view_modifier(PCall::delegation_amount_selectors()); + tester.test_view_modifier(PCall::is_in_top_delegations_selectors()); tester.test_view_modifier(PCall::min_delegation_selectors()); tester.test_view_modifier(PCall::candidate_count_selectors()); tester.test_view_modifier(PCall::round_selectors()); @@ -183,6 +187,126 @@ fn points_non_zero() { }); } +#[test] +fn delegation_amount_zero() { + ExtBuilder::default() + .with_balances(vec![(Alice.into(), 1_000)]) + .build() + .execute_with(|| { + precompiles() + .prepare_test( + Alice, + Precompile1, + PCall::delegation_amount { + candidate: Address(Alice.into()), + delegator: Address(Alice.into()), + }, + ) + .expect_cost(0) // TODO: Test db read/write costs + .expect_no_logs() + .execute_returns_encoded(0u32); + }); +} + +#[test] +fn delegation_amount_nonzero() { + ExtBuilder::default() + .with_balances(vec![(Alice.into(), 1_000), (Bob.into(), 1_000)]) + .with_candidates(vec![(Alice.into(), 1_000)]) + .with_delegations(vec![(Bob.into(), Alice.into(), 1_000)]) + .build() + .execute_with(|| { + precompiles() + .prepare_test( + Alice, + Precompile1, + PCall::delegation_amount { + candidate: Address(Alice.into()), + delegator: Address(Bob.into()), + }, + ) + .expect_cost(0) // TODO: Test db read/write costs + .expect_no_logs() + .execute_returns_encoded(1000u32); + }); +} + +#[test] +fn is_not_in_top_delegations_when_delegation_dne() { + ExtBuilder::default() + .with_balances(vec![(Alice.into(), 1_000)]) + .build() + .execute_with(|| { + precompiles() + .prepare_test( + Alice, + Precompile1, + PCall::delegation_amount { + candidate: Address(Alice.into()), + delegator: Address(Alice.into()), + }, + ) + .expect_cost(0) // TODO: Test db read/write costs + .expect_no_logs() + .execute_returns_encoded(false); + }); +} + +#[test] +fn is_not_in_top_delegations_because_not_in_top() { + ExtBuilder::default() + .with_balances(vec![ + (Alice.into(), 1_000), + (Bob.into(), 500), + (Charlie.into(), 501), + (David.into(), 502), + ]) + .with_candidates(vec![(Alice.into(), 1_000)]) + .with_delegations(vec![ + (Bob.into(), Alice.into(), 500), + (Charlie.into(), Alice.into(), 501), + (David.into(), Alice.into(), 502), + ]) + .build() + .execute_with(|| { + precompiles() + .prepare_test( + Alice, + Precompile1, + PCall::is_in_top_delegations { + candidate: Address(Alice.into()), + delegator: Address(Bob.into()), + }, + ) + .expect_cost(0) // TODO: Test db read/write costs + .expect_no_logs() + .execute_returns_encoded(false); + }); +} + +#[test] +fn is_in_top_delegations() { + ExtBuilder::default() + .with_balances(vec![(Alice.into(), 1_000), (Bob.into(), 500)]) + .with_candidates(vec![(Alice.into(), 1_000)]) + .with_delegations(vec![(Bob.into(), Alice.into(), 500)]) + .build() + .execute_with(|| { + precompiles() + .prepare_test( + Alice, + Precompile1, + PCall::is_in_top_delegations { + candidate: Address(Alice.into()), + delegator: Address(Bob.into()), + }, + ) + .expect_cost(0) // TODO: Test db read/write costs + .expect_no_logs() + .execute_returns_encoded(true); + }); +} + #[test] fn round_works() { ExtBuilder::default().build().execute_with(|| { From 5afc234cd0bc6e1a59bfffcf1c5d9fcad7f0b082 Mon Sep 17 00:00:00 2001 From: 4meta5 Date: Tue, 13 Dec 2022 21:41:44 -0500 Subject: [PATCH 2/8] fix order of arguments so it is delegator candidate to match delegation request is pending order --- precompiles/parachain-staking/StakingInterface.sol | 8 ++++---- precompiles/parachain-staking/src/lib.rs | 4 ++-- precompiles/parachain-staking/src/tests.rs | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/precompiles/parachain-staking/StakingInterface.sol b/precompiles/parachain-staking/StakingInterface.sol index 23fb2a5439..99ea97870f 100644 --- a/precompiles/parachain-staking/StakingInterface.sol +++ b/precompiles/parachain-staking/StakingInterface.sol @@ -45,20 +45,20 @@ interface ParachainStaking { /// @dev The amount delegated in support of the candidate by the delegator /// @custom:selector a73e51bc - /// @param candidate The candidate for which the delegation is in support of /// @param delegator Who made this delegation + /// @param candidate The candidate for which the delegation is in support of /// @return The amount of the delegation in support of the candidate by the delegator - function delegationAmount(address candidate, address delegator) + function delegationAmount(address delegator, address candidate) external view returns (uint256); /// @dev Whether the delegation is in the top delegations /// @custom:selector 91cc8657 - /// @param candidate The candidate for which the delegation is in support of /// @param delegator Who made this delegation + /// @param candidate The candidate for which the delegation is in support of /// @return If delegation is in top delegations (is counted) - function isInTopDelegations(address candidate, address delegator) + function isInTopDelegations(address delegator, address candidate) external view returns (bool); diff --git a/precompiles/parachain-staking/src/lib.rs b/precompiles/parachain-staking/src/lib.rs index 506ac126f5..be28cd3009 100644 --- a/precompiles/parachain-staking/src/lib.rs +++ b/precompiles/parachain-staking/src/lib.rs @@ -200,8 +200,8 @@ where #[precompile::view] fn delegation_amount( handle: &mut impl PrecompileHandle, - candidate: Address, delegator: Address, + candidate: Address, ) -> EvmResult { // Fetch info. handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; @@ -245,8 +245,8 @@ where #[precompile::view] fn is_in_top_delegations( handle: &mut impl PrecompileHandle, - candidate: Address, delegator: Address, + candidate: Address, ) -> EvmResult { let (candidate, delegator) = ( Runtime::AddressMapping::into_account_id(candidate.0), diff --git a/precompiles/parachain-staking/src/tests.rs b/precompiles/parachain-staking/src/tests.rs index 278ef7aee5..480fea8112 100644 --- a/precompiles/parachain-staking/src/tests.rs +++ b/precompiles/parachain-staking/src/tests.rs @@ -198,8 +198,8 @@ fn delegation_amount_zero() { Alice, Precompile1, PCall::delegation_amount { - candidate: Address(Alice.into()), delegator: Address(Alice.into()), + candidate: Address(Alice.into()), }, ) .expect_cost(0) // TODO: Test db read/write costs @@ -221,8 +221,8 @@ fn delegation_amount_nonzero() { Alice, Precompile1, PCall::delegation_amount { - candidate: Address(Alice.into()), delegator: Address(Bob.into()), + candidate: Address(Alice.into()), }, ) .expect_cost(0) // TODO: Test db read/write costs @@ -242,8 +242,8 @@ fn is_not_in_top_delegations_when_delegation_dne() { Alice, Precompile1, PCall::delegation_amount { - candidate: Address(Alice.into()), delegator: Address(Alice.into()), + candidate: Address(Alice.into()), }, ) .expect_cost(0) // TODO: Test db read/write costs @@ -274,8 +274,8 @@ fn is_not_in_top_delegations_because_not_in_top() { Alice, Precompile1, PCall::is_in_top_delegations { - candidate: Address(Alice.into()), delegator: Address(Bob.into()), + candidate: Address(Alice.into()), }, ) .expect_cost(0) // TODO: Test db read/write costs @@ -297,8 +297,8 @@ fn is_in_top_delegations() { Alice, Precompile1, PCall::is_in_top_delegations { - candidate: Address(Alice.into()), delegator: Address(Bob.into()), + candidate: Address(Alice.into()), }, ) .expect_cost(0) // TODO: Test db read/write costs From 2462efdca1417f5ae8e11e417bfef88904ed073c Mon Sep 17 00:00:00 2001 From: 4meta5 Date: Wed, 14 Dec 2022 22:00:17 -0500 Subject: [PATCH 3/8] add precompile getters check to TS precompile staking --- .../test-precompile-staking.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/tests/test-precompile/test-precompile-staking.ts b/tests/tests/test-precompile/test-precompile-staking.ts index 460ae18cb3..bbf595cbea 100644 --- a/tests/tests/test-precompile/test-precompile-staking.ts +++ b/tests/tests/test-precompile/test-precompile-staking.ts @@ -137,6 +137,32 @@ describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (con ).to.equal(alith.address, "delegation didn't go through"); expect(delegatorsAfter.status.toString()).equal("Active"); }); + + it("should have correct delegation amount for ethan to ALITH", async function () { + // Check that delegation amount equals MIN_GLMR_STAKING + const { result } = await web3EthCall(context.web3, { + to: PRECOMPILE_PARACHAIN_STAKING_ADDRESS, + data: PARACHAIN_STAKING_INTERFACE.encodeFunctionData("delegationAmount", [ + ethan.address, + alith.address, + ]), + }); + + expect(Number(result)).to.equal(MIN_GLMR_STAKING); + }); + + it("should have ethan's delegation to ALITH in top delegations", async function () { + // Check that delegation is in top delegations + const { result } = await web3EthCall(context.web3, { + to: PRECOMPILE_PARACHAIN_STAKING_ADDRESS, + data: PARACHAIN_STAKING_INTERFACE.encodeFunctionData("isInTopDelegations", [ + ethan.address, + alith.address, + ]), + }); + + expect(result).to.equal(true); + }); }); describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (context) => { From 5c692c3eae4ce1c3555ec509117c8499c5cb5eeb Mon Sep 17 00:00:00 2001 From: 4meta5 Date: Wed, 14 Dec 2022 22:26:15 -0500 Subject: [PATCH 4/8] compile staking interface for TS tests --- .../contracts/compiled/ParachainStaking.json | 144 +++++++++++++++++- 1 file changed, 141 insertions(+), 3 deletions(-) diff --git a/tests/contracts/compiled/ParachainStaking.json b/tests/contracts/compiled/ParachainStaking.json index c0550d4580..3bae4f6b36 100644 --- a/tests/contracts/compiled/ParachainStaking.json +++ b/tests/contracts/compiled/ParachainStaking.json @@ -105,6 +105,54 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "candidate", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint8", "name": "autoCompound", "type": "uint8" }, + { + "internalType": "uint256", + "name": "candidateDelegationCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "candidateAutoCompoundingDelegationCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorDelegationCount", + "type": "uint256" + } + ], + "name": "delegateWithAutoCompound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "delegator", "type": "address" }, + { "internalType": "address", "name": "candidate", "type": "address" } + ], + "name": "delegationAmount", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "delegator", "type": "address" }, + { "internalType": "address", "name": "candidate", "type": "address" } + ], + "name": "delegationAutoCompound", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "address", "name": "delegator", "type": "address" }, @@ -215,6 +263,16 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "delegator", "type": "address" }, + { "internalType": "address", "name": "candidate", "type": "address" } + ], + "name": "isInTopDelegations", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "address", "name": "candidate", "type": "address" } @@ -323,6 +381,26 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "candidate", "type": "address" }, + { "internalType": "uint8", "name": "value", "type": "uint8" }, + { + "internalType": "uint256", + "name": "candidateAutoCompoundingDelegationCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorDelegationCount", + "type": "uint256" + } + ], + "name": "setAutoCompound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ], "devdoc": { @@ -397,6 +475,40 @@ "delegatorDelegationCount": "The number of existing delegations by the caller" } }, + "delegateWithAutoCompound(address,uint256,uint8,uint256,uint256,uint256)": { + "custom:selector": "4b8bc9bf", + "details": "Make a delegation in support of a collator candidate", + "params": { + "amount": "The amount bonded in support of the collator candidate", + "autoCompound": "The percent of reward that should be auto-compounded", + "candidate": "The address of the supported collator candidate", + "candidateAutoCompoundingDelegationCount": "The number of auto-compounding delegations in support of the candidate", + "candidateDelegationCount": "The number of delegations in support of the candidate", + "delegatorDelegationCount": "The number of existing delegations by the caller" + } + }, + "delegationAmount(address,address)": { + "custom:selector": "a73e51bc", + "details": "The amount delegated in support of the candidate by the delegator", + "params": { + "candidate": "The candidate for which the delegation is in support of", + "delegator": "Who made this delegation" + }, + "returns": { + "_0": "The amount of the delegation in support of the candidate by the delegator" + } + }, + "delegationAutoCompound(address,address)": { + "custom:selector": "b4d4c7fd", + "details": "Returns the percent value of auto-compound set for a delegation", + "params": { + "candidate": "the candidate for which the delegation was made", + "delegator": "the delegator that made the delegation" + }, + "returns": { + "_0": "Percent of rewarded amount that is auto-compounded on each payout" + } + }, "delegationRequestIsPending(address,address)": { "custom:selector": "3b16def8", "details": "Whether there exists a pending request for a delegation made by a delegator", @@ -483,6 +595,17 @@ "_0": "A boolean confirming whether the address is a delegator" } }, + "isInTopDelegations(address,address)": { + "custom:selector": "91cc8657", + "details": "Whether the delegation is in the top delegations", + "params": { + "candidate": "The candidate for which the delegation is in support of", + "delegator": "Who made this delegation" + }, + "returns": { + "_0": "If delegation is in top delegations (is counted)" + } + }, "isSelectedCandidate(address)": { "custom:selector": "740d7d2a", "details": "Check whether the specifies address is currently a part of the active set", @@ -558,6 +681,16 @@ "custom:selector": "bcf868a6", "details": "Get the selected candidates for the current round", "returns": { "_0": "The selected candidate accounts" } + }, + "setAutoCompound(address,uint8,uint256,uint256)": { + "custom:selector": "faa1786f", + "details": "Sets an auto-compound value for a delegation", + "params": { + "candidate": "The address of the supported collator candidate", + "candidateAutoCompoundingDelegationCount": "The number of auto-compounding delegations in support of the candidate", + "delegatorDelegationCount": "The number of existing delegations by the caller", + "value": "The percent of reward that should be auto-compounded" + } } }, "title": "Pallet Parachain Staking Interface", @@ -595,6 +728,9 @@ "candidateExitIsPending(address)": "43443682", "candidateRequestIsPending(address)": "d0deec11", "delegate(address,uint256,uint256,uint256)": "829f5ee3", + "delegateWithAutoCompound(address,uint256,uint8,uint256,uint256,uint256)": "4b8bc9bf", + "delegationAmount(address,address)": "a73e51bc", + "delegationAutoCompound(address,address)": "b4d4c7fd", "delegationRequestIsPending(address,address)": "3b16def8", "delegatorBondMore(address,uint256)": "0465135b", "delegatorDelegationCount(address)": "067ec822", @@ -606,6 +742,7 @@ "goOnline()": "6e5b676b", "isCandidate(address)": "d51b9e93", "isDelegator(address)": "fd8ab482", + "isInTopDelegations(address,address)": "91cc8657", "isSelectedCandidate(address)": "740d7d2a", "joinCandidates(uint256,uint256)": "1f2f83ad", "minDelegation()": "02985992", @@ -616,11 +753,12 @@ "scheduleLeaveCandidates(uint256)": "b1a3c1b7", "scheduleLeaveDelegators()": "f939dadb", "scheduleRevokeDelegation(address)": "1a1c740c", - "selectedCandidates()": "bcf868a6" + "selectedCandidates()": "bcf868a6", + "setAutoCompound(address,uint8,uint256,uint256)": "faa1786f" } }, "ewasm": { "wasm": "" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"cancelCandidateBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"cancelDelegationRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"candidateCount\",\"type\":\"uint256\"}],\"name\":\"cancelLeaveCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLeaveDelegators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"more\",\"type\":\"uint256\"}],\"name\":\"candidateBondMore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"candidateDelegationCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"candidateExitIsPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"candidateRequestIsPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"candidateDelegationCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorDelegationCount\",\"type\":\"uint256\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"delegationRequestIsPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"more\",\"type\":\"uint256\"}],\"name\":\"delegatorBondMore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegatorDelegationCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"executeCandidateBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"executeDelegationRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"candidateDelegationCount\",\"type\":\"uint256\"}],\"name\":\"executeLeaveCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"delegatorDelegationCount\",\"type\":\"uint256\"}],\"name\":\"executeLeaveDelegators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"goOffline\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"goOnline\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"isDelegator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"isSelectedCandidate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"candidateCount\",\"type\":\"uint256\"}],\"name\":\"joinCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minDelegation\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"round\",\"type\":\"uint256\"}],\"name\":\"points\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"round\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"less\",\"type\":\"uint256\"}],\"name\":\"scheduleCandidateBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"less\",\"type\":\"uint256\"}],\"name\":\"scheduleDelegatorBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"candidateCount\",\"type\":\"uint256\"}],\"name\":\"scheduleLeaveCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scheduleLeaveDelegators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"scheduleRevokeDelegation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"selectedCandidates\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"The Moonbeam Team\",\"custom:address\":\"0x0000000000000000000000000000000000000800\",\"details\":\"The interface through which solidity contracts will interact with Parachain Staking We follow this same interface including four-byte function selectors, in the precompile that wraps the pallet\",\"kind\":\"dev\",\"methods\":{\"cancelCandidateBondLess()\":{\"custom:selector\":\"b5ad5f07\",\"details\":\"Cancel pending candidate bond request\"},\"cancelDelegationRequest(address)\":{\"custom:selector\":\"c90eee83\",\"details\":\"Cancel pending delegation request (already made in support of input by caller)\",\"params\":{\"candidate\":\"The address of the candidate\"}},\"cancelLeaveCandidates(uint256)\":{\"custom:selector\":\"9c76ebb4\",\"details\":\"Cancel request to leave the set of collator candidates\",\"params\":{\"candidateCount\":\"The number of candidates in the CandidatePool\"}},\"cancelLeaveDelegators()\":{\"custom:selector\":\"f7421284\",\"details\":\"Cancel request to leave the set of delegators\"},\"candidateBondMore(uint256)\":{\"custom:selector\":\"a52c8643\",\"details\":\"Request to bond more for collator candidates\",\"params\":{\"more\":\"The additional amount self-bonded\"}},\"candidateCount()\":{\"custom:selector\":\"a9a981a3\",\"details\":\"Get the CandidateCount weight hint\",\"returns\":{\"_0\":\"The CandidateCount weight hint\"}},\"candidateDelegationCount(address)\":{\"custom:selector\":\"2ec087eb\",\"details\":\"Get the CandidateDelegationCount weight hint\",\"params\":{\"candidate\":\"The address for which we are querying the nomination count\"},\"returns\":{\"_0\":\"The number of nominations backing the collator\"}},\"candidateExitIsPending(address)\":{\"custom:selector\":\"43443682\",\"details\":\"Whether there exists a pending exit for candidate\",\"params\":{\"candidate\":\"the candidate for which the exit request was made\"},\"returns\":{\"_0\":\"Whether a pending request exists for such delegation\"}},\"candidateRequestIsPending(address)\":{\"custom:selector\":\"d0deec11\",\"details\":\"Whether there exists a pending bond less request made by a candidate\",\"params\":{\"candidate\":\"the candidate which made the request\"},\"returns\":{\"_0\":\"Whether a pending bond less request was made by the candidate\"}},\"delegate(address,uint256,uint256,uint256)\":{\"custom:selector\":\"829f5ee3\",\"details\":\"Make a delegation in support of a collator candidate\",\"params\":{\"amount\":\"The amount bonded in support of the collator candidate\",\"candidate\":\"The address of the supported collator candidate\",\"candidateDelegationCount\":\"The number of delegations in support of the candidate\",\"delegatorDelegationCount\":\"The number of existing delegations by the caller\"}},\"delegationRequestIsPending(address,address)\":{\"custom:selector\":\"3b16def8\",\"details\":\"Whether there exists a pending request for a delegation made by a delegator\",\"params\":{\"candidate\":\"the candidate for which the delegation was made\",\"delegator\":\"the delegator that made the delegation\"},\"returns\":{\"_0\":\"Whether a pending request exists for such delegation\"}},\"delegatorBondMore(address,uint256)\":{\"custom:selector\":\"0465135b\",\"details\":\"Bond more for delegators with respect to a specific collator candidate\",\"params\":{\"candidate\":\"The address of the collator candidate for which delegation shall increase\",\"more\":\"The amount by which the delegation is increased\"}},\"delegatorDelegationCount(address)\":{\"custom:selector\":\"067ec822\",\"details\":\"Get the DelegatorDelegationCount weight hint\",\"params\":{\"delegator\":\"The address for which we are querying the delegation count\"},\"returns\":{\"_0\":\"The number of delegations made by the delegator\"}},\"executeCandidateBondLess(address)\":{\"custom:selector\":\"2e290290\",\"details\":\"Execute pending candidate bond request\",\"params\":{\"candidate\":\"The address for the candidate for which the request will be executed\"}},\"executeDelegationRequest(address,address)\":{\"custom:selector\":\"e98c8abe\",\"details\":\"Execute pending delegation request (if exists && is due)\",\"params\":{\"candidate\":\"The address of the candidate\",\"delegator\":\"The address of the delegator\"}},\"executeLeaveCandidates(address,uint256)\":{\"custom:selector\":\"3867f308\",\"details\":\"Execute due request to leave the set of collator candidates\",\"params\":{\"candidate\":\"The candidate address for which the pending exit request will be executed\",\"candidateDelegationCount\":\"The number of delegations for the candidate to be revoked\"}},\"executeLeaveDelegators(address,uint256)\":{\"custom:selector\":\"fb1e2bf9\",\"details\":\"Execute request to leave the set of delegators and revoke all delegations\",\"params\":{\"delegator\":\"The leaving delegator\",\"delegatorDelegationCount\":\"The number of active delegations to be revoked by delegator\"}},\"goOffline()\":{\"custom:selector\":\"a6485ccd\",\"details\":\"Temporarily leave the set of collator candidates without unbonding\"},\"goOnline()\":{\"custom:selector\":\"6e5b676b\",\"details\":\"Rejoin the set of collator candidates if previously had called `goOffline`\"},\"isCandidate(address)\":{\"custom:selector\":\"d51b9e93\",\"details\":\"Check whether the specified address is currently a collator candidate\",\"params\":{\"candidate\":\"the address that we want to confirm is a collator andidate\"},\"returns\":{\"_0\":\"A boolean confirming whether the address is a collator candidate\"}},\"isDelegator(address)\":{\"custom:selector\":\"fd8ab482\",\"details\":\"Check whether the specified address is currently a staking delegator\",\"params\":{\"delegator\":\"the address that we want to confirm is a delegator\"},\"returns\":{\"_0\":\"A boolean confirming whether the address is a delegator\"}},\"isSelectedCandidate(address)\":{\"custom:selector\":\"740d7d2a\",\"details\":\"Check whether the specifies address is currently a part of the active set\",\"params\":{\"candidate\":\"the address that we want to confirm is a part of the active set\"},\"returns\":{\"_0\":\"A boolean confirming whether the address is a part of the active set\"}},\"joinCandidates(uint256,uint256)\":{\"custom:selector\":\"1f2f83ad\",\"details\":\"Join the set of collator candidates\",\"params\":{\"amount\":\"The amount self-bonded by the caller to become a collator candidate\",\"candidateCount\":\"The number of candidates in the CandidatePool\"}},\"minDelegation()\":{\"custom:selector\":\"02985992\",\"details\":\"Get the minimum delegation amount\",\"returns\":{\"_0\":\"The minimum delegation amount\"}},\"points(uint256)\":{\"custom:selector\":\"9799b4e7\",\"details\":\"Total points awarded to all collators in a particular round\",\"params\":{\"round\":\"the round for which we are querying the points total\"},\"returns\":{\"_0\":\"The total points awarded to all collators in the round\"}},\"round()\":{\"custom:selector\":\"146ca531\",\"details\":\"Get the current round number\",\"returns\":{\"_0\":\"The current round number\"}},\"scheduleCandidateBondLess(uint256)\":{\"custom:selector\":\"60744ae0\",\"details\":\"Request to bond less for collator candidates\",\"params\":{\"less\":\"The amount to be subtracted from self-bond and unreserved\"}},\"scheduleDelegatorBondLess(address,uint256)\":{\"custom:selector\":\"c172fd2b\",\"details\":\"Request to bond less for delegators with respect to a specific collator candidate\",\"params\":{\"candidate\":\"The address of the collator candidate for which delegation shall decrease\",\"less\":\"The amount by which the delegation is decreased (upon execution)\"}},\"scheduleLeaveCandidates(uint256)\":{\"custom:selector\":\"b1a3c1b7\",\"details\":\"Request to leave the set of collator candidates\",\"params\":{\"candidateCount\":\"The number of candidates in the CandidatePool\"}},\"scheduleLeaveDelegators()\":{\"custom:selector\":\"f939dadb\",\"details\":\"Request to leave the set of delegators\"},\"scheduleRevokeDelegation(address)\":{\"custom:selector\":\"1a1c740c\",\"details\":\"Request to revoke an existing delegation\",\"params\":{\"candidate\":\"The address of the collator candidate which will no longer be supported\"}},\"selectedCandidates()\":{\"custom:selector\":\"bcf868a6\",\"details\":\"Get the selected candidates for the current round\",\"returns\":{\"_0\":\"The selected candidate accounts\"}}},\"title\":\"Pallet Parachain Staking Interface\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"cancelLeaveDelegators()\":{\"notice\":\"DEPRECATED use batch util with cancelDelegationRequest for all delegations\"},\"executeLeaveDelegators(address,uint256)\":{\"notice\":\"DEPRECATED use batch util with executeDelegationRequest for all delegations\"},\"scheduleLeaveDelegators()\":{\"notice\":\"DEPRECATED use batch util with scheduleRevokeDelegation for all delegations\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"main.sol\":\"ParachainStaking\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"main.sol\":{\"keccak256\":\"0xc2183fc3fff6f149986a58a201d841fc75ffdd8b7df4e69d311db18e511b2bf3\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://16a13dbc4b6c597bc3301fa76c77a39c5cdabffa11fd940a3321067605241549\",\"dweb:/ipfs/QmRiUWwUENwYtutUxsmNkHPfBXHPu4uCovzJGCXPE1rnkt\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.11+commit.d7f03943\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"cancelCandidateBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"cancelDelegationRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"candidateCount\",\"type\":\"uint256\"}],\"name\":\"cancelLeaveCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLeaveDelegators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"more\",\"type\":\"uint256\"}],\"name\":\"candidateBondMore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"candidateDelegationCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"candidateExitIsPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"candidateRequestIsPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"candidateDelegationCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorDelegationCount\",\"type\":\"uint256\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"autoCompound\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"candidateDelegationCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"candidateAutoCompoundingDelegationCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorDelegationCount\",\"type\":\"uint256\"}],\"name\":\"delegateWithAutoCompound\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"delegationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"delegationAutoCompound\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"delegationRequestIsPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"more\",\"type\":\"uint256\"}],\"name\":\"delegatorBondMore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegatorDelegationCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"executeCandidateBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"executeDelegationRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"candidateDelegationCount\",\"type\":\"uint256\"}],\"name\":\"executeLeaveCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"delegatorDelegationCount\",\"type\":\"uint256\"}],\"name\":\"executeLeaveDelegators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"goOffline\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"goOnline\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"isDelegator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"isInTopDelegations\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"isSelectedCandidate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"candidateCount\",\"type\":\"uint256\"}],\"name\":\"joinCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minDelegation\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"round\",\"type\":\"uint256\"}],\"name\":\"points\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"round\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"less\",\"type\":\"uint256\"}],\"name\":\"scheduleCandidateBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"less\",\"type\":\"uint256\"}],\"name\":\"scheduleDelegatorBondLess\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"candidateCount\",\"type\":\"uint256\"}],\"name\":\"scheduleLeaveCandidates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scheduleLeaveDelegators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"}],\"name\":\"scheduleRevokeDelegation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"selectedCandidates\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"candidate\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"value\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"candidateAutoCompoundingDelegationCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorDelegationCount\",\"type\":\"uint256\"}],\"name\":\"setAutoCompound\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"The Moonbeam Team\",\"custom:address\":\"0x0000000000000000000000000000000000000800\",\"details\":\"The interface through which solidity contracts will interact with Parachain Staking We follow this same interface including four-byte function selectors, in the precompile that wraps the pallet\",\"kind\":\"dev\",\"methods\":{\"cancelCandidateBondLess()\":{\"custom:selector\":\"b5ad5f07\",\"details\":\"Cancel pending candidate bond request\"},\"cancelDelegationRequest(address)\":{\"custom:selector\":\"c90eee83\",\"details\":\"Cancel pending delegation request (already made in support of input by caller)\",\"params\":{\"candidate\":\"The address of the candidate\"}},\"cancelLeaveCandidates(uint256)\":{\"custom:selector\":\"9c76ebb4\",\"details\":\"Cancel request to leave the set of collator candidates\",\"params\":{\"candidateCount\":\"The number of candidates in the CandidatePool\"}},\"cancelLeaveDelegators()\":{\"custom:selector\":\"f7421284\",\"details\":\"Cancel request to leave the set of delegators\"},\"candidateBondMore(uint256)\":{\"custom:selector\":\"a52c8643\",\"details\":\"Request to bond more for collator candidates\",\"params\":{\"more\":\"The additional amount self-bonded\"}},\"candidateCount()\":{\"custom:selector\":\"a9a981a3\",\"details\":\"Get the CandidateCount weight hint\",\"returns\":{\"_0\":\"The CandidateCount weight hint\"}},\"candidateDelegationCount(address)\":{\"custom:selector\":\"2ec087eb\",\"details\":\"Get the CandidateDelegationCount weight hint\",\"params\":{\"candidate\":\"The address for which we are querying the nomination count\"},\"returns\":{\"_0\":\"The number of nominations backing the collator\"}},\"candidateExitIsPending(address)\":{\"custom:selector\":\"43443682\",\"details\":\"Whether there exists a pending exit for candidate\",\"params\":{\"candidate\":\"the candidate for which the exit request was made\"},\"returns\":{\"_0\":\"Whether a pending request exists for such delegation\"}},\"candidateRequestIsPending(address)\":{\"custom:selector\":\"d0deec11\",\"details\":\"Whether there exists a pending bond less request made by a candidate\",\"params\":{\"candidate\":\"the candidate which made the request\"},\"returns\":{\"_0\":\"Whether a pending bond less request was made by the candidate\"}},\"delegate(address,uint256,uint256,uint256)\":{\"custom:selector\":\"829f5ee3\",\"details\":\"Make a delegation in support of a collator candidate\",\"params\":{\"amount\":\"The amount bonded in support of the collator candidate\",\"candidate\":\"The address of the supported collator candidate\",\"candidateDelegationCount\":\"The number of delegations in support of the candidate\",\"delegatorDelegationCount\":\"The number of existing delegations by the caller\"}},\"delegateWithAutoCompound(address,uint256,uint8,uint256,uint256,uint256)\":{\"custom:selector\":\"4b8bc9bf\",\"details\":\"Make a delegation in support of a collator candidate\",\"params\":{\"amount\":\"The amount bonded in support of the collator candidate\",\"autoCompound\":\"The percent of reward that should be auto-compounded\",\"candidate\":\"The address of the supported collator candidate\",\"candidateAutoCompoundingDelegationCount\":\"The number of auto-compounding delegations in support of the candidate\",\"candidateDelegationCount\":\"The number of delegations in support of the candidate\",\"delegatorDelegationCount\":\"The number of existing delegations by the caller\"}},\"delegationAmount(address,address)\":{\"custom:selector\":\"a73e51bc\",\"details\":\"The amount delegated in support of the candidate by the delegator\",\"params\":{\"candidate\":\"The candidate for which the delegation is in support of\",\"delegator\":\"Who made this delegation\"},\"returns\":{\"_0\":\"The amount of the delegation in support of the candidate by the delegator\"}},\"delegationAutoCompound(address,address)\":{\"custom:selector\":\"b4d4c7fd\",\"details\":\"Returns the percent value of auto-compound set for a delegation\",\"params\":{\"candidate\":\"the candidate for which the delegation was made\",\"delegator\":\"the delegator that made the delegation\"},\"returns\":{\"_0\":\"Percent of rewarded amount that is auto-compounded on each payout\"}},\"delegationRequestIsPending(address,address)\":{\"custom:selector\":\"3b16def8\",\"details\":\"Whether there exists a pending request for a delegation made by a delegator\",\"params\":{\"candidate\":\"the candidate for which the delegation was made\",\"delegator\":\"the delegator that made the delegation\"},\"returns\":{\"_0\":\"Whether a pending request exists for such delegation\"}},\"delegatorBondMore(address,uint256)\":{\"custom:selector\":\"0465135b\",\"details\":\"Bond more for delegators with respect to a specific collator candidate\",\"params\":{\"candidate\":\"The address of the collator candidate for which delegation shall increase\",\"more\":\"The amount by which the delegation is increased\"}},\"delegatorDelegationCount(address)\":{\"custom:selector\":\"067ec822\",\"details\":\"Get the DelegatorDelegationCount weight hint\",\"params\":{\"delegator\":\"The address for which we are querying the delegation count\"},\"returns\":{\"_0\":\"The number of delegations made by the delegator\"}},\"executeCandidateBondLess(address)\":{\"custom:selector\":\"2e290290\",\"details\":\"Execute pending candidate bond request\",\"params\":{\"candidate\":\"The address for the candidate for which the request will be executed\"}},\"executeDelegationRequest(address,address)\":{\"custom:selector\":\"e98c8abe\",\"details\":\"Execute pending delegation request (if exists && is due)\",\"params\":{\"candidate\":\"The address of the candidate\",\"delegator\":\"The address of the delegator\"}},\"executeLeaveCandidates(address,uint256)\":{\"custom:selector\":\"3867f308\",\"details\":\"Execute due request to leave the set of collator candidates\",\"params\":{\"candidate\":\"The candidate address for which the pending exit request will be executed\",\"candidateDelegationCount\":\"The number of delegations for the candidate to be revoked\"}},\"executeLeaveDelegators(address,uint256)\":{\"custom:selector\":\"fb1e2bf9\",\"details\":\"Execute request to leave the set of delegators and revoke all delegations\",\"params\":{\"delegator\":\"The leaving delegator\",\"delegatorDelegationCount\":\"The number of active delegations to be revoked by delegator\"}},\"goOffline()\":{\"custom:selector\":\"a6485ccd\",\"details\":\"Temporarily leave the set of collator candidates without unbonding\"},\"goOnline()\":{\"custom:selector\":\"6e5b676b\",\"details\":\"Rejoin the set of collator candidates if previously had called `goOffline`\"},\"isCandidate(address)\":{\"custom:selector\":\"d51b9e93\",\"details\":\"Check whether the specified address is currently a collator candidate\",\"params\":{\"candidate\":\"the address that we want to confirm is a collator andidate\"},\"returns\":{\"_0\":\"A boolean confirming whether the address is a collator candidate\"}},\"isDelegator(address)\":{\"custom:selector\":\"fd8ab482\",\"details\":\"Check whether the specified address is currently a staking delegator\",\"params\":{\"delegator\":\"the address that we want to confirm is a delegator\"},\"returns\":{\"_0\":\"A boolean confirming whether the address is a delegator\"}},\"isInTopDelegations(address,address)\":{\"custom:selector\":\"91cc8657\",\"details\":\"Whether the delegation is in the top delegations\",\"params\":{\"candidate\":\"The candidate for which the delegation is in support of\",\"delegator\":\"Who made this delegation\"},\"returns\":{\"_0\":\"If delegation is in top delegations (is counted)\"}},\"isSelectedCandidate(address)\":{\"custom:selector\":\"740d7d2a\",\"details\":\"Check whether the specifies address is currently a part of the active set\",\"params\":{\"candidate\":\"the address that we want to confirm is a part of the active set\"},\"returns\":{\"_0\":\"A boolean confirming whether the address is a part of the active set\"}},\"joinCandidates(uint256,uint256)\":{\"custom:selector\":\"1f2f83ad\",\"details\":\"Join the set of collator candidates\",\"params\":{\"amount\":\"The amount self-bonded by the caller to become a collator candidate\",\"candidateCount\":\"The number of candidates in the CandidatePool\"}},\"minDelegation()\":{\"custom:selector\":\"02985992\",\"details\":\"Get the minimum delegation amount\",\"returns\":{\"_0\":\"The minimum delegation amount\"}},\"points(uint256)\":{\"custom:selector\":\"9799b4e7\",\"details\":\"Total points awarded to all collators in a particular round\",\"params\":{\"round\":\"the round for which we are querying the points total\"},\"returns\":{\"_0\":\"The total points awarded to all collators in the round\"}},\"round()\":{\"custom:selector\":\"146ca531\",\"details\":\"Get the current round number\",\"returns\":{\"_0\":\"The current round number\"}},\"scheduleCandidateBondLess(uint256)\":{\"custom:selector\":\"60744ae0\",\"details\":\"Request to bond less for collator candidates\",\"params\":{\"less\":\"The amount to be subtracted from self-bond and unreserved\"}},\"scheduleDelegatorBondLess(address,uint256)\":{\"custom:selector\":\"c172fd2b\",\"details\":\"Request to bond less for delegators with respect to a specific collator candidate\",\"params\":{\"candidate\":\"The address of the collator candidate for which delegation shall decrease\",\"less\":\"The amount by which the delegation is decreased (upon execution)\"}},\"scheduleLeaveCandidates(uint256)\":{\"custom:selector\":\"b1a3c1b7\",\"details\":\"Request to leave the set of collator candidates\",\"params\":{\"candidateCount\":\"The number of candidates in the CandidatePool\"}},\"scheduleLeaveDelegators()\":{\"custom:selector\":\"f939dadb\",\"details\":\"Request to leave the set of delegators\"},\"scheduleRevokeDelegation(address)\":{\"custom:selector\":\"1a1c740c\",\"details\":\"Request to revoke an existing delegation\",\"params\":{\"candidate\":\"The address of the collator candidate which will no longer be supported\"}},\"selectedCandidates()\":{\"custom:selector\":\"bcf868a6\",\"details\":\"Get the selected candidates for the current round\",\"returns\":{\"_0\":\"The selected candidate accounts\"}},\"setAutoCompound(address,uint8,uint256,uint256)\":{\"custom:selector\":\"faa1786f\",\"details\":\"Sets an auto-compound value for a delegation\",\"params\":{\"candidate\":\"The address of the supported collator candidate\",\"candidateAutoCompoundingDelegationCount\":\"The number of auto-compounding delegations in support of the candidate\",\"delegatorDelegationCount\":\"The number of existing delegations by the caller\",\"value\":\"The percent of reward that should be auto-compounded\"}}},\"title\":\"Pallet Parachain Staking Interface\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"cancelLeaveDelegators()\":{\"notice\":\"DEPRECATED use batch util with cancelDelegationRequest for all delegations\"},\"executeLeaveDelegators(address,uint256)\":{\"notice\":\"DEPRECATED use batch util with executeDelegationRequest for all delegations\"},\"scheduleLeaveDelegators()\":{\"notice\":\"DEPRECATED use batch util with scheduleRevokeDelegation for all delegations\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"main.sol\":\"ParachainStaking\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"main.sol\":{\"keccak256\":\"0x3ffc82c52662ab3e20b69c094d5e175eed6b8712a133bd9cb36f678cd0d0ff4a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://8f8a5a4bb251a4ceffb9c036643dfc45e8ec47f9f85a342b05b6153bcedd50fb\",\"dweb:/ipfs/Qmb7Nx8GhJ3mfYYoKFF6Rakt5skCk6w2xLCk7dhBaEFMo7\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null }, "userdoc": { "kind": "user", @@ -638,5 +776,5 @@ "version": 1 } }, - "sourceCode": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity >=0.8.3;\n\n/// @dev The ParachainStaking contract's address.\naddress constant PARACHAIN_STAKING_ADDRESS = 0x0000000000000000000000000000000000000800;\n\n/// @dev The ParachainStaking contract's instance.\nParachainStaking constant PARACHAIN_STAKING_CONTRACT = ParachainStaking(\n PARACHAIN_STAKING_ADDRESS\n);\n\n/// @author The Moonbeam Team\n/// @title Pallet Parachain Staking Interface\n/// @dev The interface through which solidity contracts will interact with Parachain Staking\n/// We follow this same interface including four-byte function selectors, in the precompile that\n/// wraps the pallet\n/// @custom:address 0x0000000000000000000000000000000000000800\ninterface ParachainStaking {\n /// @dev Check whether the specified address is currently a staking delegator\n /// @custom:selector fd8ab482\n /// @param delegator the address that we want to confirm is a delegator\n /// @return A boolean confirming whether the address is a delegator\n function isDelegator(address delegator) external view returns (bool);\n\n /// @dev Check whether the specified address is currently a collator candidate\n /// @custom:selector d51b9e93\n /// @param candidate the address that we want to confirm is a collator andidate\n /// @return A boolean confirming whether the address is a collator candidate\n function isCandidate(address candidate) external view returns (bool);\n\n /// @dev Check whether the specifies address is currently a part of the active set\n /// @custom:selector 740d7d2a\n /// @param candidate the address that we want to confirm is a part of the active set\n /// @return A boolean confirming whether the address is a part of the active set\n function isSelectedCandidate(address candidate)\n external\n view\n returns (bool);\n\n /// @dev Total points awarded to all collators in a particular round\n /// @custom:selector 9799b4e7\n /// @param round the round for which we are querying the points total\n /// @return The total points awarded to all collators in the round\n function points(uint256 round) external view returns (uint256);\n\n /// @dev Get the minimum delegation amount\n /// @custom:selector 02985992\n /// @return The minimum delegation amount\n function minDelegation() external view returns (uint256);\n\n /// @dev Get the CandidateCount weight hint\n /// @custom:selector a9a981a3\n /// @return The CandidateCount weight hint\n function candidateCount() external view returns (uint256);\n\n /// @dev Get the current round number\n /// @custom:selector 146ca531\n /// @return The current round number\n function round() external view returns (uint256);\n\n /// @dev Get the CandidateDelegationCount weight hint\n /// @custom:selector 2ec087eb\n /// @param candidate The address for which we are querying the nomination count\n /// @return The number of nominations backing the collator\n function candidateDelegationCount(address candidate)\n external\n view\n returns (uint256);\n\n /// @dev Get the DelegatorDelegationCount weight hint\n /// @custom:selector 067ec822\n /// @param delegator The address for which we are querying the delegation count\n /// @return The number of delegations made by the delegator\n function delegatorDelegationCount(address delegator)\n external\n view\n returns (uint256);\n\n /// @dev Get the selected candidates for the current round\n /// @custom:selector bcf868a6\n /// @return The selected candidate accounts\n function selectedCandidates() external view returns (address[] memory);\n\n /// @dev Whether there exists a pending request for a delegation made by a delegator\n /// @custom:selector 3b16def8\n /// @param delegator the delegator that made the delegation\n /// @param candidate the candidate for which the delegation was made\n /// @return Whether a pending request exists for such delegation\n function delegationRequestIsPending(address delegator, address candidate)\n external\n view\n returns (bool);\n\n /// @dev Whether there exists a pending exit for candidate\n /// @custom:selector 43443682\n /// @param candidate the candidate for which the exit request was made\n /// @return Whether a pending request exists for such delegation\n function candidateExitIsPending(address candidate)\n external\n view\n returns (bool);\n\n /// @dev Whether there exists a pending bond less request made by a candidate\n /// @custom:selector d0deec11\n /// @param candidate the candidate which made the request\n /// @return Whether a pending bond less request was made by the candidate\n function candidateRequestIsPending(address candidate)\n external\n view\n returns (bool);\n\n /// @dev Join the set of collator candidates\n /// @custom:selector 1f2f83ad\n /// @param amount The amount self-bonded by the caller to become a collator candidate\n /// @param candidateCount The number of candidates in the CandidatePool\n function joinCandidates(uint256 amount, uint256 candidateCount) external;\n\n /// @dev Request to leave the set of collator candidates\n /// @custom:selector b1a3c1b7\n /// @param candidateCount The number of candidates in the CandidatePool\n function scheduleLeaveCandidates(uint256 candidateCount) external;\n\n /// @dev Execute due request to leave the set of collator candidates\n /// @custom:selector 3867f308\n /// @param candidate The candidate address for which the pending exit request will be executed\n /// @param candidateDelegationCount The number of delegations for the candidate to be revoked\n function executeLeaveCandidates(\n address candidate,\n uint256 candidateDelegationCount\n ) external;\n\n /// @dev Cancel request to leave the set of collator candidates\n /// @custom:selector 9c76ebb4\n /// @param candidateCount The number of candidates in the CandidatePool\n function cancelLeaveCandidates(uint256 candidateCount) external;\n\n /// @dev Temporarily leave the set of collator candidates without unbonding\n /// @custom:selector a6485ccd\n function goOffline() external;\n\n /// @dev Rejoin the set of collator candidates if previously had called `goOffline`\n /// @custom:selector 6e5b676b\n function goOnline() external;\n\n /// @dev Request to bond more for collator candidates\n /// @custom:selector a52c8643\n /// @param more The additional amount self-bonded\n function candidateBondMore(uint256 more) external;\n\n /// @dev Request to bond less for collator candidates\n /// @custom:selector 60744ae0\n /// @param less The amount to be subtracted from self-bond and unreserved\n function scheduleCandidateBondLess(uint256 less) external;\n\n /// @dev Execute pending candidate bond request\n /// @custom:selector 2e290290\n /// @param candidate The address for the candidate for which the request will be executed\n function executeCandidateBondLess(address candidate) external;\n\n /// @dev Cancel pending candidate bond request\n /// @custom:selector b5ad5f07\n function cancelCandidateBondLess() external;\n\n /// @dev Make a delegation in support of a collator candidate\n /// @custom:selector 829f5ee3\n /// @param candidate The address of the supported collator candidate\n /// @param amount The amount bonded in support of the collator candidate\n /// @param candidateDelegationCount The number of delegations in support of the candidate\n /// @param delegatorDelegationCount The number of existing delegations by the caller\n function delegate(\n address candidate,\n uint256 amount,\n uint256 candidateDelegationCount,\n uint256 delegatorDelegationCount\n ) external;\n\n /// @notice DEPRECATED use batch util with scheduleRevokeDelegation for all delegations\n /// @dev Request to leave the set of delegators\n /// @custom:selector f939dadb\n function scheduleLeaveDelegators() external;\n\n /// @notice DEPRECATED use batch util with executeDelegationRequest for all delegations\n /// @dev Execute request to leave the set of delegators and revoke all delegations\n /// @custom:selector fb1e2bf9\n /// @param delegator The leaving delegator\n /// @param delegatorDelegationCount The number of active delegations to be revoked by delegator\n function executeLeaveDelegators(\n address delegator,\n uint256 delegatorDelegationCount\n ) external;\n\n /// @notice DEPRECATED use batch util with cancelDelegationRequest for all delegations\n /// @dev Cancel request to leave the set of delegators\n /// @custom:selector f7421284\n function cancelLeaveDelegators() external;\n\n /// @dev Request to revoke an existing delegation\n /// @custom:selector 1a1c740c\n /// @param candidate The address of the collator candidate which will no longer be supported\n function scheduleRevokeDelegation(address candidate) external;\n\n /// @dev Bond more for delegators with respect to a specific collator candidate\n /// @custom:selector 0465135b\n /// @param candidate The address of the collator candidate for which delegation shall increase\n /// @param more The amount by which the delegation is increased\n function delegatorBondMore(address candidate, uint256 more) external;\n\n /// @dev Request to bond less for delegators with respect to a specific collator candidate\n /// @custom:selector c172fd2b\n /// @param candidate The address of the collator candidate for which delegation shall decrease\n /// @param less The amount by which the delegation is decreased (upon execution)\n function scheduleDelegatorBondLess(address candidate, uint256 less)\n external;\n\n /// @dev Execute pending delegation request (if exists && is due)\n /// @custom:selector e98c8abe\n /// @param delegator The address of the delegator\n /// @param candidate The address of the candidate\n function executeDelegationRequest(address delegator, address candidate)\n external;\n\n /// @dev Cancel pending delegation request (already made in support of input by caller)\n /// @custom:selector c90eee83\n /// @param candidate The address of the candidate\n function cancelDelegationRequest(address candidate) external;\n}\n" + "sourceCode": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity >=0.8.3;\n\n/// @dev The ParachainStaking contract's address.\naddress constant PARACHAIN_STAKING_ADDRESS = 0x0000000000000000000000000000000000000800;\n\n/// @dev The ParachainStaking contract's instance.\nParachainStaking constant PARACHAIN_STAKING_CONTRACT = ParachainStaking(\n PARACHAIN_STAKING_ADDRESS\n);\n\n/// @author The Moonbeam Team\n/// @title Pallet Parachain Staking Interface\n/// @dev The interface through which solidity contracts will interact with Parachain Staking\n/// We follow this same interface including four-byte function selectors, in the precompile that\n/// wraps the pallet\n/// @custom:address 0x0000000000000000000000000000000000000800\ninterface ParachainStaking {\n /// @dev Check whether the specified address is currently a staking delegator\n /// @custom:selector fd8ab482\n /// @param delegator the address that we want to confirm is a delegator\n /// @return A boolean confirming whether the address is a delegator\n function isDelegator(address delegator) external view returns (bool);\n\n /// @dev Check whether the specified address is currently a collator candidate\n /// @custom:selector d51b9e93\n /// @param candidate the address that we want to confirm is a collator andidate\n /// @return A boolean confirming whether the address is a collator candidate\n function isCandidate(address candidate) external view returns (bool);\n\n /// @dev Check whether the specifies address is currently a part of the active set\n /// @custom:selector 740d7d2a\n /// @param candidate the address that we want to confirm is a part of the active set\n /// @return A boolean confirming whether the address is a part of the active set\n function isSelectedCandidate(address candidate)\n external\n view\n returns (bool);\n\n /// @dev Total points awarded to all collators in a particular round\n /// @custom:selector 9799b4e7\n /// @param round the round for which we are querying the points total\n /// @return The total points awarded to all collators in the round\n function points(uint256 round) external view returns (uint256);\n\n /// @dev The amount delegated in support of the candidate by the delegator\n /// @custom:selector a73e51bc\n /// @param delegator Who made this delegation\n /// @param candidate The candidate for which the delegation is in support of\n /// @return The amount of the delegation in support of the candidate by the delegator\n function delegationAmount(address delegator, address candidate)\n external\n view\n returns (uint256);\n\n /// @dev Whether the delegation is in the top delegations\n /// @custom:selector 91cc8657\n /// @param delegator Who made this delegation\n /// @param candidate The candidate for which the delegation is in support of\n /// @return If delegation is in top delegations (is counted)\n function isInTopDelegations(address delegator, address candidate)\n external\n view\n returns (bool);\n\n /// @dev Get the minimum delegation amount\n /// @custom:selector 02985992\n /// @return The minimum delegation amount\n function minDelegation() external view returns (uint256);\n\n /// @dev Get the CandidateCount weight hint\n /// @custom:selector a9a981a3\n /// @return The CandidateCount weight hint\n function candidateCount() external view returns (uint256);\n\n /// @dev Get the current round number\n /// @custom:selector 146ca531\n /// @return The current round number\n function round() external view returns (uint256);\n\n /// @dev Get the CandidateDelegationCount weight hint\n /// @custom:selector 2ec087eb\n /// @param candidate The address for which we are querying the nomination count\n /// @return The number of nominations backing the collator\n function candidateDelegationCount(address candidate)\n external\n view\n returns (uint256);\n\n /// @dev Get the DelegatorDelegationCount weight hint\n /// @custom:selector 067ec822\n /// @param delegator The address for which we are querying the delegation count\n /// @return The number of delegations made by the delegator\n function delegatorDelegationCount(address delegator)\n external\n view\n returns (uint256);\n\n /// @dev Get the selected candidates for the current round\n /// @custom:selector bcf868a6\n /// @return The selected candidate accounts\n function selectedCandidates() external view returns (address[] memory);\n\n /// @dev Whether there exists a pending request for a delegation made by a delegator\n /// @custom:selector 3b16def8\n /// @param delegator the delegator that made the delegation\n /// @param candidate the candidate for which the delegation was made\n /// @return Whether a pending request exists for such delegation\n function delegationRequestIsPending(address delegator, address candidate)\n external\n view\n returns (bool);\n\n /// @dev Whether there exists a pending exit for candidate\n /// @custom:selector 43443682\n /// @param candidate the candidate for which the exit request was made\n /// @return Whether a pending request exists for such delegation\n function candidateExitIsPending(address candidate)\n external\n view\n returns (bool);\n\n /// @dev Whether there exists a pending bond less request made by a candidate\n /// @custom:selector d0deec11\n /// @param candidate the candidate which made the request\n /// @return Whether a pending bond less request was made by the candidate\n function candidateRequestIsPending(address candidate)\n external\n view\n returns (bool);\n\n /// @dev Returns the percent value of auto-compound set for a delegation\n /// @custom:selector b4d4c7fd\n /// @param delegator the delegator that made the delegation\n /// @param candidate the candidate for which the delegation was made\n /// @return Percent of rewarded amount that is auto-compounded on each payout\n function delegationAutoCompound(address delegator, address candidate)\n external\n view\n returns (uint8);\n\n /// @dev Join the set of collator candidates\n /// @custom:selector 1f2f83ad\n /// @param amount The amount self-bonded by the caller to become a collator candidate\n /// @param candidateCount The number of candidates in the CandidatePool\n function joinCandidates(uint256 amount, uint256 candidateCount) external;\n\n /// @dev Request to leave the set of collator candidates\n /// @custom:selector b1a3c1b7\n /// @param candidateCount The number of candidates in the CandidatePool\n function scheduleLeaveCandidates(uint256 candidateCount) external;\n\n /// @dev Execute due request to leave the set of collator candidates\n /// @custom:selector 3867f308\n /// @param candidate The candidate address for which the pending exit request will be executed\n /// @param candidateDelegationCount The number of delegations for the candidate to be revoked\n function executeLeaveCandidates(\n address candidate,\n uint256 candidateDelegationCount\n ) external;\n\n /// @dev Cancel request to leave the set of collator candidates\n /// @custom:selector 9c76ebb4\n /// @param candidateCount The number of candidates in the CandidatePool\n function cancelLeaveCandidates(uint256 candidateCount) external;\n\n /// @dev Temporarily leave the set of collator candidates without unbonding\n /// @custom:selector a6485ccd\n function goOffline() external;\n\n /// @dev Rejoin the set of collator candidates if previously had called `goOffline`\n /// @custom:selector 6e5b676b\n function goOnline() external;\n\n /// @dev Request to bond more for collator candidates\n /// @custom:selector a52c8643\n /// @param more The additional amount self-bonded\n function candidateBondMore(uint256 more) external;\n\n /// @dev Request to bond less for collator candidates\n /// @custom:selector 60744ae0\n /// @param less The amount to be subtracted from self-bond and unreserved\n function scheduleCandidateBondLess(uint256 less) external;\n\n /// @dev Execute pending candidate bond request\n /// @custom:selector 2e290290\n /// @param candidate The address for the candidate for which the request will be executed\n function executeCandidateBondLess(address candidate) external;\n\n /// @dev Cancel pending candidate bond request\n /// @custom:selector b5ad5f07\n function cancelCandidateBondLess() external;\n\n /// @dev Make a delegation in support of a collator candidate\n /// @custom:selector 829f5ee3\n /// @param candidate The address of the supported collator candidate\n /// @param amount The amount bonded in support of the collator candidate\n /// @param candidateDelegationCount The number of delegations in support of the candidate\n /// @param delegatorDelegationCount The number of existing delegations by the caller\n function delegate(\n address candidate,\n uint256 amount,\n uint256 candidateDelegationCount,\n uint256 delegatorDelegationCount\n ) external;\n\n /// @dev Make a delegation in support of a collator candidate\n /// @custom:selector 4b8bc9bf\n /// @param candidate The address of the supported collator candidate\n /// @param amount The amount bonded in support of the collator candidate\n /// @param autoCompound The percent of reward that should be auto-compounded\n /// @param candidateDelegationCount The number of delegations in support of the candidate\n /// @param candidateAutoCompoundingDelegationCount The number of auto-compounding delegations\n /// in support of the candidate\n /// @param delegatorDelegationCount The number of existing delegations by the caller\n function delegateWithAutoCompound(\n address candidate,\n uint256 amount,\n uint8 autoCompound,\n uint256 candidateDelegationCount,\n uint256 candidateAutoCompoundingDelegationCount,\n uint256 delegatorDelegationCount\n ) external;\n\n /// @notice DEPRECATED use batch util with scheduleRevokeDelegation for all delegations\n /// @dev Request to leave the set of delegators\n /// @custom:selector f939dadb\n function scheduleLeaveDelegators() external;\n\n /// @notice DEPRECATED use batch util with executeDelegationRequest for all delegations\n /// @dev Execute request to leave the set of delegators and revoke all delegations\n /// @custom:selector fb1e2bf9\n /// @param delegator The leaving delegator\n /// @param delegatorDelegationCount The number of active delegations to be revoked by delegator\n function executeLeaveDelegators(\n address delegator,\n uint256 delegatorDelegationCount\n ) external;\n\n /// @notice DEPRECATED use batch util with cancelDelegationRequest for all delegations\n /// @dev Cancel request to leave the set of delegators\n /// @custom:selector f7421284\n function cancelLeaveDelegators() external;\n\n /// @dev Request to revoke an existing delegation\n /// @custom:selector 1a1c740c\n /// @param candidate The address of the collator candidate which will no longer be supported\n function scheduleRevokeDelegation(address candidate) external;\n\n /// @dev Bond more for delegators with respect to a specific collator candidate\n /// @custom:selector 0465135b\n /// @param candidate The address of the collator candidate for which delegation shall increase\n /// @param more The amount by which the delegation is increased\n function delegatorBondMore(address candidate, uint256 more) external;\n\n /// @dev Request to bond less for delegators with respect to a specific collator candidate\n /// @custom:selector c172fd2b\n /// @param candidate The address of the collator candidate for which delegation shall decrease\n /// @param less The amount by which the delegation is decreased (upon execution)\n function scheduleDelegatorBondLess(address candidate, uint256 less)\n external;\n\n /// @dev Execute pending delegation request (if exists && is due)\n /// @custom:selector e98c8abe\n /// @param delegator The address of the delegator\n /// @param candidate The address of the candidate\n function executeDelegationRequest(address delegator, address candidate)\n external;\n\n /// @dev Cancel pending delegation request (already made in support of input by caller)\n /// @custom:selector c90eee83\n /// @param candidate The address of the candidate\n function cancelDelegationRequest(address candidate) external;\n\n /// @dev Sets an auto-compound value for a delegation\n /// @custom:selector faa1786f\n /// @param candidate The address of the supported collator candidate\n /// @param value The percent of reward that should be auto-compounded\n /// @param candidateAutoCompoundingDelegationCount The number of auto-compounding delegations\n /// in support of the candidate\n /// @param delegatorDelegationCount The number of existing delegations by the caller\n function setAutoCompound(\n address candidate,\n uint8 value,\n uint256 candidateAutoCompoundingDelegationCount,\n uint256 delegatorDelegationCount\n ) external;\n}\n" } From e40009278ff1a18e7cc4c60d728a7c2b55290b5a Mon Sep 17 00:00:00 2001 From: 4meta5 Date: Wed, 14 Dec 2022 22:50:22 -0500 Subject: [PATCH 5/8] try fix serialization ts error --- tests/tests/test-precompile/test-precompile-staking.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/test-precompile/test-precompile-staking.ts b/tests/tests/test-precompile/test-precompile-staking.ts index bbf595cbea..e4cc209f3b 100644 --- a/tests/tests/test-precompile/test-precompile-staking.ts +++ b/tests/tests/test-precompile/test-precompile-staking.ts @@ -161,7 +161,7 @@ describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (con ]), }); - expect(result).to.equal(true); + expect(Number(result)).to.equal(1); }); }); From ec35546b7482af9fe90fb200d3ae3168acc8af05 Mon Sep 17 00:00:00 2001 From: Crystalin Date: Fri, 16 Dec 2022 11:32:51 +0100 Subject: [PATCH 6/8] Fix test --- tests/tests/test-precompile/test-precompile-staking.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/test-precompile/test-precompile-staking.ts b/tests/tests/test-precompile/test-precompile-staking.ts index e4cc209f3b..9a6d1e71b3 100644 --- a/tests/tests/test-precompile/test-precompile-staking.ts +++ b/tests/tests/test-precompile/test-precompile-staking.ts @@ -148,7 +148,7 @@ describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (con ]), }); - expect(Number(result)).to.equal(MIN_GLMR_STAKING); + expect(BigInt(result)).to.equal(MIN_GLMR_STAKING); }); it("should have ethan's delegation to ALITH in top delegations", async function () { From 51106f5c4a91858cdd88dcb9a4b59827ef03f3fe Mon Sep 17 00:00:00 2001 From: Amar Singh Date: Thu, 22 Dec 2022 10:37:47 -0500 Subject: [PATCH 7/8] Apply suggestions from code review Co-authored-by: Nisheeth Barthwal --- precompiles/parachain-staking/src/lib.rs | 53 +++++++----------------- 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/precompiles/parachain-staking/src/lib.rs b/precompiles/parachain-staking/src/lib.rs index be28cd3009..183f60e92e 100644 --- a/precompiles/parachain-staking/src/lib.rs +++ b/precompiles/parachain-staking/src/lib.rs @@ -209,33 +209,18 @@ where Runtime::AddressMapping::into_account_id(candidate.0), Runtime::AddressMapping::into_account_id(delegator.0), ); - let amount: U256 = if let Some(state) = - pallet_parachain_staking::Pallet::::delegator_state(&delegator) - { - // get the delegation amount - if let Some(pallet_parachain_staking::Bond { amount, .. }) = state - .delegations - .0 - .into_iter() - .find(|b| b.owner == candidate) - { - amount.into() - } else { - log::trace!( - target: "staking-precompile", - "Delegation for {:?} not found, so delegation amount is 0", - candidate - ); - U256::zero() - } - } else { - log::trace!( - target: "staking-precompile", - "Delegator state for {:?} not found, so delegation amount is 0", - delegator + let amount = pallet_parachain_staking::Pallet::::delegator_state(&delegator) + .and_then(|state| { + state + .delegations + .0 + .into_iter() + .find(|b| b.owner == candidate) + }) + .map_or( + U256::zero(), + |pallet_parachain_staking::Bond { amount, .. }| amount.into(), ); - U256::zero() - }; Ok(amount) } @@ -255,21 +240,15 @@ where // Fetch info. handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let is_in_top_delegations = if let Some(delegations) = - pallet_parachain_staking::Pallet::::top_delegations(&candidate) - { + let is_in_top_delegations = pallet_parachain_staking::Pallet::::top_delegations( + &candidate, + ) + .map_or(false, |delegations| { delegations .delegations .into_iter() .any(|b| b.owner == delegator) - } else { - log::trace!( - target: "staking-precompile", - "Candidate state for {:?} not found, so delegation is not in top", - candidate - ); - false - }; + }); Ok(is_in_top_delegations) } From 3477f0ee33d67556466a93e571606a6a3963a9fe Mon Sep 17 00:00:00 2001 From: 4meta5 Date: Sun, 25 Dec 2022 20:44:05 -0500 Subject: [PATCH 8/8] test unhappy path in ts as well --- .../test-precompile-staking.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/tests/test-precompile/test-precompile-staking.ts b/tests/tests/test-precompile/test-precompile-staking.ts index 9a6d1e71b3..a851ea3ec4 100644 --- a/tests/tests/test-precompile/test-precompile-staking.ts +++ b/tests/tests/test-precompile/test-precompile-staking.ts @@ -151,6 +151,19 @@ describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (con expect(BigInt(result)).to.equal(MIN_GLMR_STAKING); }); + it("should have 0 delegation amount for delegation that DNE", async function () { + // Check that delegation amount is 0 when delegation DNE + const { result } = await web3EthCall(context.web3, { + to: PRECOMPILE_PARACHAIN_STAKING_ADDRESS, + data: PARACHAIN_STAKING_INTERFACE.encodeFunctionData("delegationAmount", [ + alith.address, + alith.address, + ]), + }); + + expect(BigInt(result)).to.equal(0n); + }); + it("should have ethan's delegation to ALITH in top delegations", async function () { // Check that delegation is in top delegations const { result } = await web3EthCall(context.web3, { @@ -163,6 +176,18 @@ describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (con expect(Number(result)).to.equal(1); }); + + it("should not be in top delegations when delegation DNE", async function () { + const { result } = await web3EthCall(context.web3, { + to: PRECOMPILE_PARACHAIN_STAKING_ADDRESS, + data: PARACHAIN_STAKING_INTERFACE.encodeFunctionData("isInTopDelegations", [ + alith.address, + alith.address, + ]), + }); + + expect(Number(result)).to.equal(0); + }); }); describeDevMoonbeamAllEthTxTypes("Precompiles - Staking - Join Delegators", (context) => {