StakeXDCDocs
Partner Staking

Smart Contract Reference

Two contracts make up Partner Staking: PartnerStakedXDCV32 (the per-partner vault; legacy pools run PartnerStakedXDCV3) and PartnerVaultRegistry (the shared directory).

Two contracts make up Partner Staking: PartnerStakedXDC_V3_2 (the per-partner vault; legacy pools run PartnerStakedXDC_V3) and PartnerVaultRegistry (the shared directory).

Live on XDC Mainnet. The shared PartnerVaultRegistry is at 0x325DEEA5C7c0Ce0D774c4A67EcCaAf1cF8953a67. Each partner vault is a separate per-partner deployment; discover live pools via the registry's allVaults() / verifiedVaults(). See Deployed Contracts & Addresses.


PartnerStakedXDC_V3_2 — the partner vault

An ERC-4626, native-XDC, share-based liquid staking vault (ReentrancyGuard, ERC4626, Pausable, AccessControl). It is a fee-bearing copy of the flagship PrimeStakedXDC_V3_1 with separate state, token, keys, and operators. asset() is the zero address because the underlying is native XDC; totalAssets() returns trackedTotalAssets. V3.2 adds the timelocked partner fee (see below); everything else matches the audited V3 template.

Constants

ConstantValueMeaning
PLATFORM_FEE_BPS150015% protocol fee on reward inflows
PLATFORM_FEE_RECIPIENT0x1658…9127StakeXDC treasury (fee recipient)
MAX_PARTNER_FEE_BPS8500Partner fee ceiling: protocol + partner can never exceed 100% of yield
PARTNER_FEE_PUSH_GAS_LIMIT100,000Gas stipend for the partner fee push (failure defers to the pull lane)
DEFAULT_MASTERNODE_STAKE10,000,000 XDCDefault masternode size
MIN_REWARD_DISTRIBUTION1000 XDCMinimum non-privileged reward push via receive()
MAX_BUFFER_BPS5000Max liquidity buffer (50%)
DEFAULT_MAX_LOSS_BPS_PER_REPORT100010% per-report validator-loss cap
DEFAULT_MAX_DAILY_LOSS_BPS200020% rolling daily loss cap
DEFAULT_GOVERNANCE_DELAY1 dayDefault timelock (range 1 min – 30 days)

Partner fee (V3.2)

ItemDetail
partnerFeeBps / partnerFeeRecipientCurrent fee (bps of gross yield) and payee. Set in the constructor (initialPartnerFeeBps, initialPartnerFeeRecipient; zero recipient defaults to the deployer).
setPartnerFee(bps)executePartnerFee() / cancelPartnerFeeChange()Timelocked rate change (admin only, waits governanceDelay). Executing first settles accrued yield at the old rate.
setPartnerFeeRecipient(addr)executePartnerFeeRecipient() / cancelPartnerFeeRecipientChange()Timelocked recipient change (admin only).
pendingPartnerFee() / pendingPartnerFeeRecipient()Views exposing any scheduled change + its executeAfter timestamp (drives the app's staker warnings).
Failure modeIf the recipient rejects the push, the fee parks in pendingQueuedAssets[recipient] and is pulled via claimQueuedAssets — the pool never bricks.

Stake & withdraw

FunctionNotes
stake(uint256 assets) payableNative-XDC stake; msg.value must equal assets. Mints shares at the current rate.
depositNative(uint256 assets, address receiver) payableSame, crediting receiver.
deposit(...) / mint(...)Disabled. Revert NativeDepositRequired (deposits must be native, via the payable wrappers).
withdraw(uint256 shares)Legacy-compatible redeem-by-shares.
withdraw(uint256 assets, address receiver, address owner) / redeem(...)Standard ERC-4626 exits; revert if the liquid buffer can't cover them.
withdrawWithQueue(uint256 assets, address receiver)Instant if liquid, else queues a FIFO request.
redeemWithQueue(uint256 shares, address receiver)Same, by shares.
cancelQueuedWithdrawal(uint256 requestId)Cancel an unprocessed queued request; shares returned.
processWithdrawalQueue(uint256 maxRequests)Anyone can advance the queue once liquidity returns.
claimQueuedAssets(address payable receiver)Claim a deferred payout (if a queued transfer failed).
maxWithdraw / maxRedeemClamped to what the buffer can pay immediately.

Masternodes & operators

FunctionRole
addOperator / removeOperatorDEFAULT_ADMIN_ROLE
submitKYC(string)DEFAULT_ADMIN_ROLE
proposeMasternode(address candidate, uint256 amount)proposer or admin
triggerAutoPropose(uint256 maxNodes)anyone (round-robins operators when funded)
resignMasternode(address) / withdrawResignedMasternode(uint256)proposer or admin
setValidator / setMinStake / setBufferBps / setAutoProposeConfig / setOperatorScanLimit / setQueueScanLimitOPERATIONS_MANAGER_ROLE
reportValidatorLoss(address operator, uint256 assets)RISK_MANAGER_ROLE, within per-report & daily caps

Governance (timelocked, two-phase)

Direct grantRole / revokeRole / renounceRole / transferOwnership / renounceOwnership all revert. Use the scheduled flow instead:

ScheduleExecuteCancel
setProposerexecuteProposercancelProposerChange
setOperationsManagerexecuteOperationsManagercancelOperationsManagerChange
setRiskManagerexecuteRiskManagercancelRiskManagerChange
setMaxLossBpsPerReportexecuteMaxLossBpsPerReportcancelMaxLossBpsPerReportChange
setMaxDailyLossBpsexecuteMaxDailyLossBpscancelMaxDailyLossBpsChange
setGovernanceDelayexecuteGovernanceDelaycancelGovernanceDelayChange
setPartnerFeeexecutePartnerFeecancelPartnerFeeChange
setPartnerFeeRecipientexecutePartnerFeeRecipientcancelPartnerFeeRecipientChange
scheduleOwnerTransferexecuteOwnerTransfercancelOwnerTransfer

Each executes only after governanceDelay has elapsed.

Key views & marker

FunctionReturns
isPartnerStakedXDCV3()true — marker the registry/UI use to identify partner vaults (kept in V3.2)
partnerVaultVersion()2 on V3.2 pools; the call reverts on legacy V3 pools, which is how the app tells generations apart
name() / symbol()The partner's branded name/symbol
totalAssets() / desiredBuffer()Tracked NAV and target buffer
isKYCVerified(address)Whether an address is KYC'd on the validator

Notable events

Staked, Withdrawn, WithdrawalQueued / WithdrawalQueueProcessed / WithdrawalQueueCancelled, MasternodeProposed, ValidatorLossReported, PlatformFeeSkimmed(recipient, amount) (every protocol fee skim), and on V3.2: PartnerFeeSkimmed / PartnerFeeDeferred (partner fee payouts) plus PartnerFeeChangeScheduled / PartnerFeeUpdated / PartnerFeeChangeCancelled and the recipient-change equivalents (timelock transparency).


PartnerVaultRegistry: the directory

Ownable2Step; owner is StakeXDC. See Registry & Verification for the full write-up.

FunctionCallerPurpose
setCanonicalCodeHash(bytes32, bool)ownerAllow-list / revoke a canonical vault bytecode hash
register(address vault)vault adminList a vault (requires canonical codehash + admin role)
setVerified(address, bool)ownerToggle the "Verified by StakeXDC" badge
unregister(address)ownerDelist an abusive/abandoned pool
setMetadata(address, PoolMeta)vault adminSet description / website / logo / socials
allVaults / verifiedVaults / vaultsByAdmin / vaultAt / vaultsLengthviewEnumerate the directory
isRegistered / isVerified / registrantOf / metadataviewPer-vault status & data

Events: CanonicalCodeHashSet, VaultRegistered, VaultVerifiedSet, VaultUnregistered, MetadataUpdated.

Partner Staking overviewHow It WorksDeploy & List a Pool

On this page