Skip to main content

The Delegation Manager

Introducing staking pools

A staking pool is defined as a custom delegation smart contract, the associated nodes and the funds staked in the pool by participants. Node operators may wish to set up a staking pool for their nodes, which can then be funded by anyone in exchange for a proportion of the validator rewards. This form of funding the stake for validators is called delegation.

Staking pools bridge the gap between node operators, who need funds to stake for their nodes, and fund holders who wish to earn rewards by staking their funds, but are not interested in managing validator nodes.

Node operators can set up a staking pool to manage one or more validator nodes. For this purpose, they may use the delegation manager built into the MultiversX Protocol to create their own delegation contract. A delegation contract automates certain tasks required for the management of a staking pool, such as keeping track of every account that has funded the staking pool, keeping track of the nodes themselves, as well as providing information to the delegators.

info

A staking pool requires 1250 EGLD deposited by the node operator at the moment of its creation. However, 2500 EGLD is required to stake a single validator node and start earning rewards.

This page describes how to request a new delegation contract from the delegation manager and how to use it. It will focus on the delegation contract more than the delegation manager, but the two concepts are intimately linked. However, it is important to remember that it is the delegation contract which handles the staking pool and the nodes associated with it.

Note that the delegation manager is not required to set up a staking pool. For example, it is also possible to set up delegation using a regular smart contract, although that is a more complex process and is not discussed here.

Node operators may also choose to set up a delegation dashboard, although they may use any user interface or none whatsoever. As an example, the boilerplate for such a delegation dashboard can be found here: https://github.com/multiversx/mx-delegation-dapp. Alternatively, the old boilerplate is located here: https://github.com/multiversx/mx-deprecated-starter-dapp/tree/master/react-delegationdashboard.

A detailed description of the delegation process can be consulted at https://github.com/multiversx/mx-specs/blob/main/sc-delegation-specs.md.

Creating a new delegation contract

The delegation contract for a new staking pool can be created by issuing a request to the delegation manager. This is done by submitting a transaction of the following form:

NewDelegationContractTransaction {
Sender: <account address of the node operator>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6
Value: 1250000000000000000000 (1250 EGLD)
GasLimit: 60000000
Data: "createNewDelegationContract" +
"@" + <total delegation cap in EGLD, fully denominated, in hexadecimal encoding> +
"@" + <service fee as hundredths of percents, in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

The Receiver address is set to erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6, which is the fixed address of the delegation manager, located on the Metachain.

The Value is set to 1250 EGLD, which will be automatically added into the funds of the newly created delegation contract, i.e. this is the initial amount of EGLD in the staking pool. This amount of EGLD always belongs to the owner of the delegation contract.

info

The initial 1250 EGLD count towards the total delegation cap, like all the funds in the staking pool.

The initial amount of 1250 EGLD added to the pool makes the owner the first delegator of the staking pool. This means that the owner is also entitled to a proportion of the rewards, which can be claimed like any other delegator.

In the Data field, the first argument passed to createNewDelegationContract is the total delegation cap (the maximum possible size of the staking pool). It is expressed as a fully denominated amount of EGLD, meaning that it is the number of 101810^{-18} subdivisions of the EGLD, and not the actual number of EGLD tokens. The fully denominated total delegation cap must then be encoded hexadecimally. Make sure not to encode the ASCII string representing the total delegation cap.

tip

For example, to obtain the fully denominated form of 7231.941 EGLD, the amount must be multiplied by 101810^{18}, resulting in 7231941000000000000000. Do not encode the ASCII string "7231941000000000000000", but encode the integer 7231941000000000000000 itself. This would result in "01880b57b708cf408000".

Setting the total delegation cap to 0 ("00" in hexadecimal) specifies an unlimited total delegation amount. It can always be modified later (see Delegation cap).

The second argument passed to createNewDelegationContract is the service fee that will be reserved for the owner of the delegation contract. It is computed as a proportion of the total rewards earned by the validator nodes. The remaining rewards apart from this proportion will be available to delegators to either claim or redelegate. The service fee is expressed as hundredths of a percent.

tip

For example, a service fee of 37.45% is expressed by the integer 3745. This integer must then be encoded hexadecimally (3745 becomes "0ea1").

Setting the service fee to 0 ("00" in hexadecimal) specifies that no rewards are reserved for the owner of the delegation contract - all rewards will be available to the delegators. The service fee can always be modified later (see Service fee).

The following is a complete example of a transaction requesting the creation of a new delegation contract:

NewDelegationContractTransaction {
Sender: <account address of the node operator>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6
Value: 1250000000000000000000
GasLimit: 60000000
Data: "createNewDelegationContract" +
"@01880b57b708cf408000" +
"@0ea1"
}

For more details about how arguments have to be encoded, check here.

The above transaction creates a new delegation contract owned by the sender, with total delegation cap of 7231.941 EGLD and service fee of 37.45% from the rewards. Moreover, the newly created delegation contract will start with a staking pool of 1250 EGLD.

Configuring the delegation contract

The owner of the delegation contract has a number of operations at their disposal.

Metadata

The delegation contract can store information that identifies the staking pool: its human-readable name, its website and its associated GitHub identity.

SetMetadataTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 2000000
Data: "setMetaData"
"@" + <name of the staking pool, in hexadecimal encoding> +
"@" + <website of the staking pool, in hexadecimal encoding > +
"@" + <GitHub identity of the staking pool, in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

An example for the Data field that sets the name to "Test Mx Provider", the website to "testmx.provider" and the GitHub identifier to "testmxprovider" is:

    "setMetaData" +
"@54657374204d782050726f7669646572" // Test Mx Provider
"@746573746d782e70726f7669646572" // testmx.provider
"@746573746d7870726f7669646572" // testmxprovider
info

Setting the identity of the staking pool in the metadata is the first step in connecting the delegation contract and a GitHub identity. The second step is explained in the next section Display information where the inverse connection is made: from the GitHub identity to the delegation contract address.

Display information

caution

As of January 2024, the only accepted way to customize the information of a delegation contract is via MultiversX Assets.

Provisioning of information from keybase or your GitHub repository is no longer accepted.

The only accepted changes are on mx-assets identities.

You can safely delete the keybase profile and also the multiversx repository inside your organization's GitHub.

To customize the information for your delegation contract, which will be available inside the MultiversX ecosystem (such as Explorer, Web Wallet, xPortal, and so on), some additional information has to be added to the MultiversX assets repository.

In order to do so, the owner of the nodes/staking provider must open a Pull Request against https://github.com/multiversx/mx-assets (master branch).

Step 1: choose the environment

  • for mainnet go to mx-assets/identities
  • for testnet go to mx-assets/testnet/identities
  • for devnet go to mx-assets/devnet/identities

Step 2: create a directory with an unique name

Must be lowercase, alphanumeric, with no spaces. For example, my-new-identity

Step 3: add a info.json file and a logo.png

Create a info.json file where you specify the owned address(es), the name, the description and social links. Example:

{
"description": "This is my new identity",
"name": "New identity",
"website": "http://newidentity.com",
"twitter": "https://twitter.com/newidentity",
"location": "<City>, <Country>",
"owners": [
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxgeryqxzqjkh", // staking provider address
"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" // the address of regular validator nodes owner
]
}

Inside the owners array:

  • if you want to define an identity of a Staking Provider, add its SC address
  • if you want to define an identity of simple nodes, add the owner address (all the keys owned by that address will have that identity)
  • if you want to define the same identity for both a Staking Provider and simple nodes, set both the address of the Staking Provider and of the owner of the nodes

Also, upload a logo.png that will be displayed near the identity.

Step 4: Open PR and validate the ownership

After opening the PR, you also have to validate the ownership. Please refer to the this section.

Done

After the PR is merged, the specified information together with the service fee, percentage filled and APR (for Staking Providers) will be displayed across the ecosystem. If this information cannot be found a generic logo and the address is displayed.

An example of how the delegation contract will be displayed based on the information provided in the GitHub is provided below.

stakingpool

note

Before MultiversX Assets, nodes owners needed to update the Identity field inside the prefs.toml file of each node. This is not required anymore now and you can safely leave the identity empty on your node configuration.

Assets ownership validation

This applies for both adding of updating an identity over the MultiversX assets.

In order to validate the ownership of a staking provider or validator nodes, one will need to sign a message by using the owner wallet and then submit a comment on the PR with the branding of a validator node or a staking provider. In case of a staking provider, its owner must perform this message signing.

Message signing can be performed either via Web Wallet, either via MultiversX Utils. The message to be signed is the commit hash of the latest commit in the PR. Inside the PR, go to the Commits tab and copy the latest commit hash (the bottom one is the latest commit).

commit-hash

Then, by using a message signer (Web Wallet of MultiversX Utils), sign that commit hash (make sure you don't have additional spaces or other characters) by using the owner wallet.

commit-hash-sign

After that, leave a comment on that PR with the resulted signature.

commit-hash-sig-comm

That's it. A GitHub workflow will validate the signature and if everything is ok, the PR will merged by a MultiversX responsible and the identity will be live anytime soon.

Service fee

The service fee is a percentage of the validator rewards that will be reserved for the owner of the delegation contract. The rest of the rewards will be available to delegators to either claim or redelegate.

The service fee can be changed at any time using a transaction of the form:

ChangeServiceFeeTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 2000000
Data: "changeServiceFee" +
"@" + <service fee as hundredths of percents, in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

In the Data field, the only argument passed to changeServiceFee is the new value of the service fee, expressed as hundredths of a percent.

Setting the service fee to 0 ("00" in hexadecimal) specifies that no rewards are reserved for the owner of the delegation contract - all rewards will be available to the delegators. The service fee can always be modified later.

tip

For example, a service fee of 37.45% is expressed by the integer 3745. This integer must then be encoded hexadecimally (3745 becomes "0ea1").

Finally, a Data field containing changeServiceFee@0ea1 will change the service fee to 37.45%.

Automatic activation

When automatic activation is enabled, the delegation contract will activate (stake) inactive nodes as soon as funds have become available in sufficient amount. Consequently, any delegation transaction can potentially trigger the activation of inactive nodes, assuming the transaction has sufficient gas.

Automatic activation can be enabled or disabled using a transaction of the form:

SetAutomaticActivationTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 2000000
Data: "setAutomaticActivation" +
"@" + <"true" or "false" in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

The only argument passed to setAutomaticActivation is either true or false, as an ASCII string encoded hexadecimally. For reference, true is "74727565" and false is "66616c7365".

tip

For example, a Data field containing "setAutomaticActivation@74727565" enables automatic activation.

Delegation cap

The total delegation cap is the maximum possible size amount of EGLD which can be held by the delegation contract. After reaching the total delegation cap, the contract will reject any subsequent funds.

The total delegation cap can be modified at any time using a transaction of the form:

ModifyTotalDelegationCapTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 2000000
Data: "modifyTotalDelegationCap" +
"@" + <total delegation cap in EGLD, fully denominated, in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

In the Data field, the only argument passed to modifyTotalDelegationCap is the new value for the delegation cap. It is expressed as a fully denominated amount of EGLD, meaning that it is the number of 101810^{-18} subdivisions of the EGLD, and not the actual number of EGLD tokens. Take sure not to encode the ASCII string representing the total delegation cap.

tip

For example, to obtain the fully denominated form of 7231.941 EGLD, the amount must be multiplied by the denomination factor 101810^{18}, resulting in 7231941000000000000000. Do not encode the ASCII string "7231941000000000000000", but encode the integer 7231941000000000000000 itself. This would result in "01880b57b708cf408000".

Finally, a Data field containing "modifyTotalDelegationCap@01880b57b708cf408000" will change the total delegation cap to 7231.941 EGLD.

Setting the total delegation cap to 0 ("00" in hexadecimal) specifies an unlimited total delegation amount. It can always be modified later.

info

The total delegation cap cannot be set to a value lower than the amount staked for currently active nodes. It must be either higher than that amount or set to 0 (infinite cap).

Managing nodes

Adding nodes

When a delegation contract is first created, it contains no information about nodes. The owner of the contract must then register nodes into the contract, so that they can be later activated. Any newly added node is "inactive" by default.

Adding nodes requires the BLS key pairs belonging to each of them, which the owner of the contract uses to prove that they have access to the nodes. This proof consists of signing the address of the delegation contract itself with the secret BLS key of each node, individually. This results in as many signed messages as there are nodes.

Adding N nodes to the delegation contract is done by submitting a transaction with the values set as follows:

AddNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 1000000 + N·6000000
Data: "addNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <address of the delegation contract signed with the secret BLS key of the first node, in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
"@" + <address of the delegation contract signed with the secret BLS key of the second node, in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
"@" + <address of the delegation contract signed with the secret BLS key of the Nth node, in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

As shown above, the Data field contains an enumeration of N pairs. Such a pair consists of the public BLS key of a node along with the message produced by signing the address of the delegation contract with the secret BLS key of the respective node. There are as many pairs as there are nodes to add.

Staking nodes

When the staking pool held by the delegation contract contains a sufficient amount of EGLD, the inactive (non-staked) nodes can be staked (activated). This promotes the nodes to the status of validator, which means they participate in consensus and earn rewards.

This subsection describes the manual staking (activation) of nodes. To automatically stake (activate) nodes when funds become available, automatic activation can be enabled.

To stake specific nodes manually, a transaction of the following form can be submitted:

StakeNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 1000000 + N·6000000
Data: "stakeNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
}

For more details about how arguments have to be encoded, check here.

The Data field contains an enumeration of N public BLS keys corresponding to the nodes to be staked.

Unstaking nodes

Validator nodes that are already staked (active) can be manually unstaked.

info

Validators are demoted to observer status at the beginning of the next epoch after unstaking. This means that they stop receiving rewards.

Unstaking does not mean that the staked amount returns to the staking pool (see undelegating and withdrawing).

To cancel the deactivation before the unstaking is complete, the nodes can be restaked.

To begin the deactivation process for a selection of validator nodes, a transaction of the following form is used:

UnstakeNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 1000000 + N·6000000
Data: "unStakeNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
}

For more details about how arguments have to be encoded, check here.

The Data field contains an enumeration of N public BLS keys corresponding to the nodes to be unstaked.

Restaking nodes

Validator nodes that have been unstaked can be restaked (reactivated) before their deactivation is complete. To cancel their deactivation, a transaction of the following form is used:

RestakeNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 1000000 + N·6000000
Data: "reStakeUnStakedNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
}

For more details about how arguments have to be encoded, check here.

The Data field contains an enumeration of N public BLS keys corresponding to the nodes to be restaked.

Unbonding nodes

Nodes that have been unstaked can be completely deactivated, a process called unbonding.

info

Validators are demoted to observer status at the beginning of the next epoch after unstaking, not unbonding. See unstaking above.

Validator nodes that have been unbonded cannot be restaked (reactivated). They must be staked anew.

UnbondNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 1000000 + N·6000000
Data: "unBondNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
}

For more details about how arguments have to be encoded, check here.

The Data field contains an enumeration of N public BLS keys corresponding to the nodes to be unbonded.

Removing nodes

Inactive (not staked, unbonded) nodes can be removed from the delegation contract by the owner at any time. Neither active (staked) nor unstaked nodes cannot be removed.

Unlike adding nodes, this step does not require the BLS key pairs of the nodes.

Removing N nodes from the delegation contract is done by submitting a transaction with the values set as follows:

RemoveNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 1000000 + N·6000000
Data: "removeNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
}

For more details about how arguments have to be encoded, check here.

The Data field contains an enumeration of N public BLS keys corresponding to the nodes to be removed.

Unjailing nodes

When active validator nodes perform poorly or to the detriment of the network, they are penalized by having their rating reduced. Rating is essential to earning rewards, because it directly determines the likelihood of a validator to be selected for consensus.

However, it can happen that rating of a validator might drop under the acceptable threshold. As a consequence, the validator will begin its next epoch jailed, which prevents it from participating in consensus.

info

A jailed validator does not lose its stake nor its status. It remains active, but it cannot earn rewards while in jail.

Recovering a validator from jail and restoring it is called unjailing, for which a fine of 2.5 EGLD must be paid. Multiple validators can be recovered from jail at the same time by paying 2.5 EGLD for each validator. The format of the unjailing transaction is as follows:

UnjailNodesTransaction {
Sender: <account address of the delegation contract owner>
Receiver: <address of the delegation contract>
Value: 2.5 EGLD × <number of nodes to be unjailed>
GasLimit: 1000000 + N·6000000
Data: "unJailNodes" +
"@" + <public BLS key of the first node in hexadecimal encoding> +
"@" + <public BLS key of the second node in hexadecimal encoding> +
<...> +
"@" + <public BLS key of the Nth node in hexadecimal encoding> +
}

For more details about how arguments have to be encoded, check here.

Note that the Value field depends on N, the number of validators to unjail.

The Data field contains an enumeration of N public BLS keys corresponding to the nodes to be unjailed.

Delegating and managing delegated funds

Accounts that delegate their own funds to the staking pool are called delegators. The delegation contract offers them a set of actions as well. This means that these actions are available to the owner of the delegation contract as well.

Delegating funds

Accounts become delegators by funding the staking pool, i.e. they delegate their funds. The delegators are rewarded for their contribution with a proportion of the rewards earned by the validator nodes. By default, the owner of the delegation contract is the first delegator, having already contributed 1250 EGLD to the staking pool at its creation.

info

Extra funds received by the delegation contract from delegators will be immediately used to top-up the stake of the existing active validators, consequently increasing their rewards.

Submitting a delegation transaction takes into account the status of automatic activation: if the delegated funds cause the amount in the staking pool to become sufficient for the staking of extra nodes, it can trigger their activation automatically. This happens only if the transaction contains enough gas.

But if gas is insufficient, or if automatic activation is disabled, the amount received through the delegation transaction simply becomes top-up for the stake of already active validators. Subsequent manual staking will be necessary to use the funds for staking, assuming they are sufficient.

Funds can be delegated by any fund holder by submitting a transaction of the following form:

DelegateTransaction {
Sender: <account address of funds holder>
Receiver: <address of the delegation contract>
Value: minimum 1 EGLD
GasLimit: 12000000
Data: "delegate"
}

For more details about how arguments have to be encoded, check here.

If the transaction is successful, the funds' holder has become a delegator and the funds either become a top-up amount for the stake of active validators, or may trigger the staking of inactive nodes, as described above.

Claiming rewards

A portion of the rewards earned by validator nodes is reserved for each delegator. To claim the rewards, a delegator may issue a transaction of the following form:

ClaimRewardsTransaction {
Sender: <account address of existing delegator>
Receiver: <address of the delegation contract>
Value: 0
Gas: 6000000
Data: "claimRewards"
}

For more details about how arguments have to be encoded, check here.

If the transaction is successful, the delegator receives the proportion of rewards they are entitled to.

Redelegating rewards

Current delegation rewards can also be immediately delegated instead of claimed. This makes it an operation very similar to delegation.

info

Just like delegation, redelegation of rewards takes into account the status of automatic activation: if the redelegated rewards cause the amount in the staking pool to become sufficient for the staking of extra nodes, it can trigger their activation automatically (requires sufficient gas in the redelegation transaction).

Rewards are redelegated using a transaction of the form:

RedelegateRewardsTransaction {
Sender: <account address of existing delegator>
Receiver: <address of the delegation contract>
Value: 0
Gas: 12000000
Data: "reDelegateRewards"
}

For more details about how arguments have to be encoded, check here.

If the transaction is successful, the delegator does not receive any EGLD at the moment, but the rewards they were entitled to will be added to their delegated amount.

Undelegating funds

Delegators may express the intent to withdraw a specific amount of EGLD from the staking pool. However, this process cannot happen at once and may take a few epochs before the amount is actually available for withdrawal, because the funds may already be used to stake for active validators and this means that unstaking of nodes may be necessary.

info

If the amount to undelegate requested by the delegator will cause the staking pool to drop below the sufficient amount required to keep all the current validators active, some validators will inevitably end up unstaked. The owner of the delegation contract may intervene and add extra funds to prevent such situations.

Funds that have been previously used as stake for validators have been transferred into a separate system smart contract at the moment of staking, therefore the delegation contract itself does not hold these funds. But submitting an undelegation request will cause the delegation contract to attempt their retrieval.

The delegation contract may receive the funds immediately if they're not currently used as stake; this makes them available for subsequent withdrawal. This is the case where previously delegated funds acted as top-up to the stake of existing validators.

On the other hand, if the requested funds are currently in use as stake, the delegation contract cannot receive them yet.

info

Funds used as stake can only be retrieved after 144000 blocks have been built on the Metachain (a little over 10 chronological epochs). It doesn't matter whether the validator was already demoted to observer, or whether it has been decomissioned entirely - the funds may not return until the aforementioned time has passed.

After 144000 blocks, the funds can be withdrawn normally by their rightful owner.

To express the intention of future withdrawal of funds from the staking pool, a delegator may submit the following transaction:

UndelegateTransaction {
Sender: <account address of existing delegator>
Receiver: <address of the delegation contract>
Value: 0
Gas: 12000000
Data: "unDelegate"
"@" + <amount to undelegate in EGLD, minimum 1 EGLD, fully denominated, in hexadecimal encoding>
}

For more details about how arguments have to be encoded, check here.

In the Data field, the only argument passed to unDelegate is the desired amount of EGLD to undelegate and later withdraw. It is expressed as a fully denominated amount of EGLD, meaning that it is the number of 101810^{-18} subdivisions of the EGLD, and not the actual number of EGLD tokens. The fully denominated amount must then be encoded hexadecimally. Make sure not to encode the ASCII string representing the amount.

Withdrawing

After submitting an undelegation transaction, a delegator may finally withdraw funds from the staking pool.

info

Funds must always be undelegated first. They cannot be directly withdrawn.

This action withdraws all the currently undelegated funds belonging to the specific delegator.

Withdrawing funds is done using a transaction of the following form:

WithdrawTransaction {
Sender: <account address of existing delegator>
Receiver: <address of the delegation contract>
Value: 0
GasLimit: 12000000
Data: "withdraw"
}

For more details about how arguments have to be encoded, check here.

If the transaction is successful, the delegator receives all the EGLD they have previously requested to undelegate. The amount is removed from the staking pool.

Delegation contract view functions

The delegation contract can be queried using the following view functions. These queries should be done on a local proxy on the /vm-values/query endpoint.

The following documentation sections only show the value of the relevant returnData field and omit the other fields for simplicity.

{
"data": {
"data": {
"returnData": [],
"returnCode": "ok",
"returnMessage": "",
"gasRemaining": 0,
"gasRefund": 0,
"outputAccounts": null,
"deletedAccounts": null,
"touchedAccounts": null,
"logs": []
}
},
"error": "",
"code": "successful"
}

POST Contract config

The response contains an array of the properties in a fixed order (base64 encoded): owner address, service fee, maximum delegation cap, initial owner funds, automatic activation, with delegation cap, can change service fee, check cap on redelegate, nonce on creation and unbond period.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getContractConfig"
}

POST Contract metadata

The response contains an array of the properties in a fixed order (base64 encoded): staking provider name, website and identifier.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getMetaData"
}

POST Number of delegators

The response contains a value representing the number of delegators in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getNumUsers"
}

POST Number of nodes

The response contains the number of nodes in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getNumNodes"
}

POST Nodes states

The response contains an enumeration of alternating status codes and BLS keys. Each status code is followed by the BLS key of the node it describes. Both status codes and BLS keys are encoded in base64.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getAllNodeStates"
}

POST Total active stake

The response contains a value representing the total active stake in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getTotalActiveStake"
}

POST Total unstaked stake

The response contains a value representing the total unstaked stake in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getTotalUnStaked"
}

POST Total cumulated rewards

The response contains a value representing the sum of all accumulated rewards in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getTotalCumulatedRewards",
"caller": "erd1qqqqqqqqqqqqqqqpqqqqqqqqlllllllllllllllllllllllllllsr9gav8"
}

POST Delegator claimable rewards

The response contains a value representing the total claimable rewards for the delegator in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getClaimableRewards",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Delegator total accumulated rewards

The response contains a value representing the total accumulated rewards for the delegator in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getTotalCumulatedRewardsForUser",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Delegator active stake

The response contains a value representing the active stake for the delegator in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getUserActiveStake",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Delegator unstaked stake

The response contains a value representing the unstaked stake for the delegator in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getUserUnStakedValue",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Delegator unbondable stake

The response contains a value representing the unbondable stake in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getUserUnBondable",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Delegator undelegated stake

The response contains an enumeration representing the different undelegated stake values in base64 encoding of the hex encoding.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getUserUnDelegatedList",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Delegator funds data

The response contains an enumeration for the delegator encoded base64 of the hexadecimal encoding of the following: active stake, unclaimed rewards, unstaked stake and unbondable stake.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getDelegatorFundsData",
"args": [
"<delegator address in hexadecimal encoding of the bech32 decoded value>"
]
}

POST Get reward data for epoch

The response contains an enumeration for the specified epoch representing the base64 encoding of the hexadecimal encoding for the rewards to distribute, total active stake and service fee.

https://proxy:port/vm-values/query
{
"scAddress": "<address of the delegation contract in bech32 encoding>",
"funcName": "getRewardData",
"args": ["<epoch number in hexadecimal encoding>"]
}

Delegation mananger view functions

POST All contract addresses

The response contains an enumeration of bech32 keys bytes in base64 encoding.

https://proxy:port/vm-values/query
{
"scAddress": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6",
"funcName": "getAllContractAddresses"
}

POST Contract config

The response contains an enumeration of the properties in a fixed order (base64 encoded): current number of contracts, last created contract address, minimum and maximum service fee, minimum deposit and delegation.

https://proxy:port/vm-values/query
{
"scAddress": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6",
"funcName": "getContractConfig"
}