Skip to content

Latest commit

 

History

History
568 lines (390 loc) · 22.7 KB

tip-467.md

File metadata and controls

568 lines (390 loc) · 22.7 KB
tip: 467
title: Stake 2.0 - A new TRON staking model 
author: [email protected]
discussions-to: https://github.com/tronprotocol/tips/issues/467
status: Final
type: Standards Track 
category: Core
created: 2022-09-28

Simple Summary

This TIP aims to establish a more flexible stake model, called Stake 2.0, Stake 2.0 can improve the utilization of network resources, and at the same time enhance the stability of the TRON stake system.

Motivation

At present, by staking TRX on the TRON network, you can obtain voting rights called TRON Power, as well as bandwidth or energy as resources. The users need to choose whether to obtain whether energy or bandwidth during the stake operation. The obtained resources can also be delegated to other addresses only if they are specified when staking. Once the staking is completed, it is not allowed to unstake within 3 days. Then, the users can perform the unstake operation and immediately obtain the staked TRX.

The delegating of resources under the current stake mechanism is hardly flexible, resulting in low resource utilization and complicated user operations. The stake and delegating operation are bound together at present. If you want to alter your resource delegating object, you need to perform unstaking first, then make another staking and designate a new delegating object. Additionally, the unstake operation must wait for 3 days after staking, which means that the resources obtained cannot be re-delegated to others within 3 days. If the user has already voted before unstaking, the unstake operation will also result in the automatic cancellation of the vote. Hence, all these rules greatly reduce the efficiency of resource allocation and incur extremely complicated user operations to stake and delegate at will.

Since the TVM does not support stake, vote, or delegate commands, the developers are not able to implement related operations in a smart contract, which limits the applications involved staking and delegating, like tokenization and decentralized resource exchange. In addition, the principal will arrive immediately after the stake is released, when the TRX market fluctuates violently, a large number of staking or unstaking operations will be triggered, which will also have a certain impact on the overall stake model.

Therefore, we need a new stake mechanism to solve these problems, separate low-frequency staking operations and high-frequency resource delegating operations, support resource re-delegating without unstaking, and improve resource utilization. Add stake, delegate, vote, and related commands should be added in the TVM, meanwhile, the new mechanism should implement the delayed arrival of unstaking TRX, improve the stability of the stake model under extreme market conditions, and help network participants to form more stable expectations for the total circulation of the entire network.

Specifications

Based on the description above, a newly designed staking model is shown as below, seven new APIs should be added to the java-tron client:

  • /wallet/freezebalancev2
  • /wallet/unfreezebalancev2
  • /wallet/delegateresource
  • /wallet/undelegateresource
  • /wallet/withdrawexpireunfreeze
  • /wallet/getavailableunfreezecount
  • /wallet/getcanwithdrawunfreezeamount
  • /wallet/getcandelegatedmaxsize
  • /wallet/getdelegatedresourcev2
  • /wallet/getdelegatedresourceaccountindexv2

and six new opcodes should be added to TVM: FREEZEBALANCEV2, UNFREEZEBALANCEV2, DELEGATERESOURCE, UNDELEGATERESOURCE, CANCELALLUNFREEZEV2, WITHDRAWEXPIREUNFREEZE

Mechanism

The mechanism of Stake 2.0 is shown as follows:

  • User calls /wallet/freezebalancev2 to stake TRX and obtain resources, specifing the type of resource. The corresponding resource goes to the owner address that has staked TRX.
  • After staking and obtaining resources, the owner is able to call /wallet/delegateresource to delegate resources to multiple recipients respectively. The delegating time locker is an optional, if selected, the delegated resources cannot be undelegated within 3 days, if not selected, there will not be lock-up period. When the owner repeat the delegating operation with time lock of same amount to the same receiver address, the lock-up period will be reset to 3 days.
  • The owner call /wallet/undelegateresource to cancel the resource delegating for a recipient, supporting partial cancellation by amount.
  • Call /wallet/unfreezebalancev2 to unstake TRX, partial unstaking is supported, but only for the available part, TRX related to the delegated resources are considered locked and not available, therefore, cannot be unstaked.
  • After the owner performs the unstaking operation, he needs to wait N days, then call /wallet/withdrawexpireunfreeze to get back TRX,N is a TRON network parameter.

Specification in undelegateresource

If the recipient has consumed a part of the resource, after undelegating, this part of resources will still be not available status in the owner account, and needs some time to recover. The owner can only delegate the available resources to others.

Example:

  • Assuming that A has 1000 units of energy, delegate all of them to B. After B used 400 units, A called /wallet/undelegateresource to undelegate all the energy left. Now, A has a balance of 600 units of energy in the account, 400 units are in recovering.

Specification in unstake

TRX partial unstaking is supported, but a maximum of 32 partial unstaking operations is allowed simultaneously, in other words, there should be no more than 32 delay arrivals of the unstaking assets in progress at the same time.

Example,

  • Assuming N is 3, and the user staked 50 TRX. On day 1, the user unstakes 1 TRX, he needs to wait for 3 days, that is, on day 4, the user will be able to get back 1 TRX. Then on day 2, the user unstakes another 1 TRX, he would be able to get it back on day 5. Each unstaking operation needs to wait for 3 days before redeeming. There could be at most 32 unstaking operations in processing at the same time in the new model.

Unstaking will first reclaim the idle TRON Power, then the TRON Power that has been used. For the reclaiming of TRON Power that has been used, if vote for multiple SRs, it will revoke votes in proportion.

Example:

  • Suppose that a user stakes 2000 TRX and gets 2000 TRON Power, 1,000 TRON Power is idle and 1,000 TRON Power votes for 5 SRs. Each SR gets 200 votes. Now the user unstake 1500 TRX, which means 1500 TRON Power needs to be reclaimed, in this case, the 1000 idle TRON Power will be reclaimed first, then revoke 100 votes from each SR.

  • Revoked votes from SR(A) = (Total revoked votes from all SRs/ Total previous votes to all SRs) * Total previous votes to SR(A)

Specification of HTTP APIs

/wallet/freezebalancev2

Description: stake TRX to obtain TRON Power (voting rights) and bandwidth or energy.

Params:

  1. owner_address - Address of transaction initiator, data type is string
  2. frozen_balance - Amount of TRX to be staked, unit is sun, data type is uint256
  3. resource - Resource type, "BANDWIDTH" or "ENERGY", data type is string
  4. visible - Whether the address is in Base58 format, data type is bool

Returns - unsigned transaction, data type is json string

Example:

curl -X POST  http://127.0.0.1:8092/wallet/freezebalancev2 -d  \
'{"owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
 "frozen_balance":1000000,
 "resource":"BANDWIDTH",
 "visible":true
}'

/wallet/unfreezebalancev2

Description: Unstake TRX to release bandwidth and energy and at the same time TRON Power will be reduced and all corresponding votes will be canceled.

Params:

  1. owner_address - Address of transaction initiator, data type is string
  2. unfreeze_balance - Amount of TRX to be unstaked, unit is sun, data type is uint256
  3. resource - Resource type, "BANDWIDTH" or "ENERGY", data type is string
  4. visible - Whether the address is in base58 format, data type is bool

Returns - unsigned transaction, data type is json string

Example:

curl -X POST  http://127.0.0.1:8092/wallet/unfreezebalancev2 -d  \
'{"owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
 "unfreeze_balance":1000000,
 "resource":"BANDWIDTH",
 "visible":true
}'

/wallet/delegateresource

Description: delegate resource

Params:

  1. owner_address - Address of transaction initiator, data type is string
  2. receiver_address - Receiver address of resource to be delegated to
  3. balance - Amount of TRX staked for resource to be delegated, unit is sun, data type is unit256
  4. resource - Resource type, "BANDWIDTH" or "ENERGY", data type is string
  5. lock - Whether it is locked, if it is set to true, the delegated resources cannot be undelegated within 3 days.When the lock time is not over, if the owner delegates the same resources using the lock to the same address, the lock time will be reset to 3 days
  6. visible - Whether the address is in base58 format, data type is bool

Returns - unsigned transaction, data type is json string

Example:

curl -X POST  http://127.0.0.1:8092/wallet/delegateresource -d  \
'{"owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
 "receiver_address":"TQ4gjjpAjLNnE67UFbmK5wVt5fzLfyEVs3",
 "balance":1000000,
 "resource":"BANDWIDTH",
 "lock": true,
 "visible":true
}'

/wallet/undelegateresource

Description: undelegate API

Params:

  1. owner_address - Address of transaction initiator, data type is string
  2. receiver_address - Receiver address of resource to be delegated to
  3. balance - Amount of TRX staked for resource to be undelegated, unit is sun, data type is unit256
  4. resource - Resource type, "BANDWIDTH" or "ENERGY", data type is string
  5. visible - Whether the address is in base58 format, data type is bool

Returns - unsigned transaction, data type is json string

Example:

curl -X POST  http://127.0.0.1:8092/wallet/undelegateresource -d  \
'{"owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
 "receiver_address":"TQ4gjjpAjLNnE67UFbmK5wVt5fzLfyEVs3",
 "balance":1000000,
 "resource":"BANDWIDTH",
 "visible":true
}'

/wallet/withdrawexpireunfreeze

Description: withdraw unfrozen balance API

Params:

  1. owner_address - Address of transaction initiator, data type is string
  2. visible - Whether the address is in base58 format, data type is bool

Returns - unsigned transaction, data type is json string

Example:

curl -X POST  http://127.0.0.1:8092/wallet/withdrawexpireunfreeze -d  \
'{
  "owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
  "visible":true
 }'

/wallet/getavailableunfreezecount

Description: remaining times of available unstaking API

Params:

  1. owner_address - account address, data type is string.
  2. visible - whether the address is in base58 format, data type is bool

Returns - Remaining times of available unstaking, data type is number.

Example:

curl -X POST  http://127.0.0.1:8092/wallet/getavailableunfreezecount -d  \
'{
  "owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
  "visible":true
 }'

/wallet/getcanwithdrawunfreezeamount Description: query the withdrawable balance at the specified timestamp

Params:

  1. owner_address - account address, data type is string.
  2. timestamp - query cutoff timestamp, in millisecond.
  3. visible - Whether the address is in Base58 format, data type is bool

Returns - withdrawable balance,unit is sun.

Example:

curl -X POST  http://127.0.0.1:8092/wallet/getcanwithdrawunfreezeamount -d  \
'{
  "owner_address":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
  "timestamp": 1667977444000
  "visible":true
 }'

/wallet/getcandelegatedmaxsize Description: query the amount of delegatable resources of the specified resource Type for target address, unit is sun.

Params:

  1. owner_address - account address, data type is string.
  2. type - resource type,data type is number, 0 is bandwidth, 1 is energy
  3. visible - whether the address is in base58 format, data type is bool

Returns - the amount of delegatable resource, unit is sun.

Note: The interface indicates the return of the maximum amount of delegated resources for normal transactions, but there are some special transactions in actual situations, such as multi-signature, memo and other transactions that will deduct a part of the resource usage. At this time, the maximum value of specific resources that can be used may be smaller than the recommended value returned through this interface.

Example:

curl -X POST  http://127.0.0.1:8092/wallet/getcandelegatedmaxsize -d  \
'{
  "owner_address": "TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
  "type": 1,
  "visible": true
 }'

/wallet/getdelegatedresourcev2

Description: query the amount of resources detail delegated by fromAddress to toAddress

Params:

  1. fromAddress - resource from address, data type is string.
  2. toAddress - resource to address, data type is string.
  3. visible - whether the address is in base58 format, data type is bool

Returns - Resource delegation information

Example:

curl -X POST  http://127.0.0.1:8092/wallet/getdelegatedresourcev2 -d  \
'{
  "fromAddress": "TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
  "toAddress": "TQ4gjjpAjLNnE67UFbmK5wVt5fzLfyEVs3",
  "visible": true
 }'

/wallet/getdelegatedresourceaccountindexv2

Description: query the resource delegation index by an account

Params:

  1. value - account ddress, data type is string.
  2. visible - whether the address is in base58 format, data type is bool

Returns - Resource delegation index

Example:

curl -X POST  http://127.0.0.1:8092/wallet/getdelegatedresourceaccountindexv2 -d  \
'{
  "value":"TJAVcszse667FmSNCwU2fm6DmfM5D4AyDh",
  "visible": true
 }'

Specification of TVM instructions

0xda: FREEZEBALANCEV2

The FREEZEBALANCEV2 takes 2 operands pop up from stack:

  • amount: amount to freeze in SUN.
  • resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

If operation succeed, push 1 to stack, otherwise push 0 to stack.

0xdb: UNFREEZEBALANCEV2

The UNFREEZEBALANCEV2 takes 2 operands pop up from stack.

  • amount: amount to unfreeze in SUN.
  • resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

If operation succeed, push 1 to stack, otherwise push 0 to stack.

0xdc: CANCELALLUNFREEZEV2

The CANCELALLUNFREEZEV2 takes no operand pop up from stack.

If operation succeed, push 1 to stack, otherwise push 0 to stack.

0xdd: WITHDRAWEXPIREUNFREEZE

The WITHDRAWEXPIREUNFREEZE takes no operand pop up from stack.

If operation succeed, push the actual withdrawal amount to stack, otherwise push 0 to stack.

0xde: DELEGATERESOURCE

The DELEGATERESOURCE takes 3 operands pop up from stack:

  • amount: resource amount to delegate in SUN.
  • resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.
  • receiver: account address to receive the resource.

If operation succeed, push 1 to stack, otherwise push 0 to stack.

0xdf: UNDELEGATERESOURCE

The UNDELEGATERESOURCE takes 3 operands pop up from stack:

  • amount: resource amount to undelegate in SUN.
  • resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.
  • receiver: account address to return the resource.

If operation succeed, push 1 to stack, otherwise push 0 to stack.

Specification of precompile contracts

0x100000b: GetChainParameter

The GetChainParameter takes 1 parameters:

index: index of the parameter to be queried.

Query the specific chain parameters, and push the query result to stack. The solidity syntax is shown below.

  • chain.totalNetLimit
  • chain.totalNetWeight
  • chain.totalEnergyCurrentLimit
  • chain.totalEnergyWeight
  • chain.unfreezeDelayDays

0x100000c: AvailableUnfreezeV2Size

The AvailableUnfreezeV2Size takes 1 parameters:

target: target account address.

Query the size of the available unfreeze queue for target address, and push the query result to stack.

0x100000d: UnfreezableBalanceV2

The UnfreezableBalanceV2 takes 2 parameters:

target: target account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the unfreezable balance of a specified resourceType for target address, and push the query result to stack.

0x100000e: ExpireUnfreezeBalanceV2

The ExpireUnfreezeBalanceV2 takes 2 parameters:

target: target account address.

timestamp: query cutoff timestamp.

Query the withdrawal balance at the specified timestamp for target address, and push the query result to stack.

0x100000f: DelegatableResource

The DelegatableResource takes 2 parameters:

target: target account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the amount of delegatable resources(unit: SUN) of the specified resourceType for target address, and push the query result to stack.

0x1000010: ResourceV2

The ResourceV2 takes 3 parameters:

target: target account address.

from: from account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the amount of resources(unit: SUN) of a specific resourceType delegated by from address to target address

0x1000011: CheckUnDelegateResource

The CheckUnDelegateResource takes 3 parameters:

target: target account address.

amount: resource amount to undelegate in SUN.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Check whether the contract can recycle the specified amount of resources of a specific resourceType that have been delegated to target address, and push the amount of clean resource(unit: SUN), the amount of dirty resource(unit: SUN) and the restore time to stack.

0x1000012: ResourceUsage

The ResourceUsage takes 2 parametes:

target: target account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the usage of a specific resourceType of resources for target address, and push the amount of usage(unit: SUN) and the restore time to stack.

0x1000013: TotalResource

The TotalResource takes 2 parameters:

target: target account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the total amount of available resources(unit: SUN) of a specific resourceType for target address, and push the query reslut to stack.

0x1000014: TotalDelegatedResource

The TotalDelegatedResource takes 2 parameters:

target: target account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the amount of delegated resources of a specific resourceType for target address, and push the query reslut to stack.

0x1000015: TotalAcquiredResource

The TotalAcquiredResource takes 2 parameters:

target: target account address.

resourceType: 0 as bandwidth, 1 as energy, 2 as tron power.

Query the amount of acquired resources(unit: SUN) of a specific resourceType for tareget address, and push the query reslut to stack.

Solidity example

Here is an example showing how to call the above TVM instructions in solidity:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract FreezeV2Example {

    event BalanceFreezedV2(uint, uint);
    event BalanceUnfreezedV2(uint, uint);
    event AllUnFreezeV2Canceled();
    event ExpireUnfreezeWithdrew(uint);
    event ResourceDelegated(uint, uint, address);
    event ResourceUnDelegated(uint, uint, address);

    constructor() payable {}

    fallback() payable external {}

    receive() payable external {}

    function freezeBalanceV2(uint amount, uint resourceType) external {
        freezebalancev2(amount, resourceType);
        emit BalanceFreezedV2(amount, resourceType);
    }

    function unfreezeBalanceV2(uint amount, uint resourceType) external {
        unfreezebalancev2(amount, resourceType);
        emit BalanceUnfreezedV2(amount, resourceType);
    }

    function cancelAllUnfreezeV2() external {
        cancelallunfreezev2();
        emit AllUnFreezeV2Canceled();
    }

    function withdrawExpireUnfreeze() external returns(uint amount) {
        amount = withdrawexpireunfreeze();
        emit ExpireUnfreezeWithdrew(amount);
    }

    function delegateResource(uint amount, uint resourceType, address payable receiver) external {
        receiver.delegateResource(amount, resourceType);
        emit ResourceDelegated(amount, resourceType, receiver);
    }

    function unDelegateResource(uint amount, uint resourceType, address payable receiver) external {
        receiver.unDelegateResource(amount, resourceType);
        emit ResourceUnDelegated(amount, resourceType, receiver);
    }

    function getChainParameters() view public returns(uint, uint, uint, uint, uint) {
        return (chain.totalNetLimit, chain.totalNetWeight,
                chain.totalEnergyCurrentLimit, chain.totalEnergyWeight,
                chain.unfreezeDelayDays);
    }

    function getAvailableUnfreezeV2Size(address target) view public returns(uint) {
        return target.availableUnfreezeV2Size();
    }

    function getUnfreezableBalanceV2(address target, uint resourceType) view public returns(uint) {
        return target.unfreezableBalanceV2(resourceType);
    }

    function getExpireUnfreezeBalanceV2(address target, uint timestamp) view public returns(uint) {
        return target.expireUnfreezeBalanceV2(timestamp);
    }

    function getDelegatableResource(address target, uint resourceType) view public returns(uint, uint) {
        return (target.delegatableResource(resourceType), block.number);
    }

    function getResourceV2(address target, address from, uint resourceType) view public returns(uint) {
        return target.resourceV2(from, resourceType);
    }

    function checkUnDelegateResource(address target, uint amount, uint resourceType) view public returns(uint, uint, uint, uint) {
        (uint clean, uint dirty, uint restoreTime) = target.checkUnDelegateResource(amount, resourceType);
        return (clean, dirty, restoreTime, block.number);
    }

    function getResourceUsage(address target, uint resourceType) view public returns(uint, uint, uint) {
        (uint dirty, uint restoreTime) = target.resourceUsage(resourceType);
        return (dirty, restoreTime, block.number);
    }

    function getTotalResource(address target, uint resourceType) view public returns(uint) {
        return target.totalResource(resourceType);
    }

    function getTotalDelegatedResource(address from, uint resourceType) view public returns(uint) {
        return from.totalDelegatedResource(resourceType);
    }

    function getTotalAcquiredResource(address target, uint resourceType) view public returns(uint) {
        return target.totalAcquiredResource(resourceType);
    }

    function killme(address payable target) external {
        selfdestruct(target);
    }
}

Backward Compatibility

After the proposal of the new mechanism is opened, it will not affect the previously frozen TRX. For those TRX frozen through the old mechanism, it can be redeemed using the old unstake interface. If needed, the only way to stake in the future is through the new mechanism.