Skip to content

Latest commit

 

History

History
268 lines (181 loc) · 8.44 KB

tip-271.md

File metadata and controls

268 lines (181 loc) · 8.44 KB
tip: 271
title: Vote for SR in Smart Contract
author: yanghang8612<[email protected]>
status: Final
type: Standards Track
category: VM
created: 2021-06-01

Simple Summary

To provide vote related operations in TVM.

Abstract

VoteWitness & WithdrawReward operations in system contract are introduced, smart contract can vote for witness and get reward from the system.

Motivation

Common user can vote for activated witness to share the block reward. However, non-privatekey accounts, like smart contracts, can not get benefit from this incentive mechanism.

Meanwhile, after TIP-157 activating on the mainnet, smart contracts can freeze their balance to get resources include tron power. But this part of resources can not be used because there is no vote related instructions in TVM.

So this TIP aims to implement the incentive voting functionalities for smart contracts. On one hand, smart contracts will take fully advantage of their balance. For example, voting witness, keeping the network safe, sharing the block reward. On the other hand, developer could write some special voting contracts to provide a new way to vote witness for common user which is different from system voting contract. These voting contracts may be more complex to system voting contract and provide more attractive and unique voting feature.

Specifications

New instructions

0xd8: VOTEWITNESS

The VOTE takes 4 operands pop up from stack:

tronPowerArrayLength: witness address array offset.

tronPowerArrayOffset: witness address array size.

witnessAddressArrayLength: tron power number array offset.

witnessAddressArrayOffset: tron power number array size.

TVM will get witness array from memory by using witnessOffset and witnessSize.

TVM will get tron power array from memory by using tronPowerOffset and tronPowerSize.

Execute vote function and push 0 to stack if fail, push 1 otherwize.

0xd9: WITHDRAWREWARD

The WITHDRAWREWARD takes no operand pop up from stack.

Execute withdraw function and push actually withdrawed reward amout to stack.

New precompile contracts

0x1000005: RewardBalance

The RewardBalance takes no operand pop up from stack.

Execute query reward function and push reward amount which can be withdrawed to stack.

0x1000006: IsSrCandidate

The IsSrCandidate takes 1 operand pop up from stack:

targetAddress: target account address.

Push 0 if target address is not a witness, otherwise push 1.

0x1000007: VoteCount

The VoteCount takes 2 operand pop up from stack:

voteAddress: vote account address.

targetAddress: target account address.

Execute query vote count function and push vote count to stack.

0x1000008: UsedVoteCount

The UsedVoteCount takes 1 operand pop up from stack:

voteAddress: vote account address.

Execute query total used vote count function.

0x1000009: ReceivedVoteCount

The ReceviedVoteCount takes 1 operand pop up from stack:

receivedAddress: witness address.

Excute query witness total received vote count.

0x100000a: TotalVoteCount

The TotalVoteCount takes 1 operand pop up from stack:

voteAddress: vote account address.

Execute query total vote count function.

Solidity Example

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.5.18 || ^0.6.13 || ^0.7.7 || ^0.8.6;

contract TestVote {

    /**
     * @dev Contract can accept value while creating.
     */
    constructor() public payable {}

    /**
     * Due to the introduction of Stake2.0, we have removed the Stake1.0 related example codes.
     * Please add the appropriate staking codes here according to the version of the staking mechanism.
     */
    // Staking related code here

    /**
     * @dev Vote witness in `srList` array and every witness will get correspond 
     * tron power in `tpList` array.
     *
     * Below situations can cause `revert` exception:
     * 1. `srList` array length and `tpList` array length are different.
     * 2. Array length are greater than MAX_VOTE_NUMBER (30).
     * 3. There are normal account address in `srList` array.
     * 4. There are negative value in 'tpList' array.
     * 5. Total needed tron power is greater than current owned tron power of contract.
     */
    function voteWitness(address[] calldata srList, uint[] calldata tpList) external {
        vote(srList, tpList);
    }

    /**
     * @dev Withdraw all allowance and reward to contract balance. 
     * @return Actually withdrawn balance of allowance and reward. 
     *
     * Below situations can cause `revert` exception:
     * 1. Contract address is in witness list of genesis block.
     * 2. Sum of contract balance and reward overflow long (8 bytes).
     *
     * Caution:
     * 1. Current cycle reward can not be withdrawed.
     */
    function withdrawReward() external returns(uint) {
        return withdrawreward();
    }

    /**
     * @dev Query all allowance and reward of contract account.
     * @return Sum of allowance and reward of contradct account.
     *
     * caution:
     * 1. Current cycle reward is excluded
     */
    function queryRewardBalance() external view returns(uint) {
        return rewardBalance();
    }

    /**
     * @dev Judge whether the address is a candidate address.
     * @return If the address is a candidate address, return `true`, otherwise return `false`.
     */
    function isWitness(address sr) external view returns(bool) {
        return isSrCandidate(sr);
    }

    /**
     * @dev Query vote count of `from` account voting for `to` account.
     * @return Corresponding vote count (tron-power, 1 trx = 1 tron-power).
     */
    function queryVoteCount(address from, address to) external view returns(uint) {
        return voteCount(from, to);
    }

    /**
     * @dev Query total vote count of `owner` (Also can be called tron-power owned by contract).
     * @return Total vote count of `owner` account (tron-power, 1 trx = 1 tron-power).
     */
    function queryTotalVoteCount(address owner) external view returns(uint) {
        return totalVoteCount(owner);
    }

     /**
     * @dev Query `owner` recevied vote count.
     * @return Received vote count of `owner` account (tron-power, 1 trx = 1 tron-power).
     */
    function queryReceivedVoteCount(address owner) external view returns(uint) {
        return receivedVoteCount(owner);
    }

    /**
     * @dev Query `owner` used vote count.
     * @return Used vote count of `owner` account (tron-power, 1 trx = 1 tron-power).
     */
    function queryUsedVoteCount(address owner) external view returns(uint) {
        return usedVoteCount(owner);
    }

    /**
     * @dev Execute self destruct and transfer all balance and asset of contract to target address.
     *
     * Below situations can cause `revert` exception:
     * 1. There are still delegated frozen balance for other account address.
     *
     * Caution
     * 1. The operation will auto clear votes and withdraw all allowance and reward to contract balance.
     */
    function killme(address payable target) external {
        selfdestruct(target);
    }
}

Notice

For vote(address[], uint[]), if array length in memory does not match the parameter length, a ByteExecutionexception will throw.

For vote(address[], uint[]), if address array length and uint array length is different, a revert exception will throw.

For withdrawreward(), withdraw all rewards to contract balance.

Both vote(address[], uint[]) and withdrawreward() will change the state of storage, so they can not be executed in static context (a static context can only be created by staticcall now). Otherwise, a StaticCallModificationexception will throw.

New reward calculation algorithm

See author`s blog for more details of the algorithm at Read the docs

Rationale

Tier

VOTEWITNESS: tier.ExtTier

WITHDRAWREWARD: tier.ExtTier

Energy cost

Instructions

VOTEWITNESS: 30000 energy

WITHDRAWREWARD: 20000 energy

Precomplie contracts

RewardBalance: 500 energy

IsSrCandidate: 20 energy

VoteCount: 500 energy

UsedVoteCount: 20 energy

ReceivedVoteCount: 20 energy

TotalVoteCount: 20 energy

Selfdestruct

If contract still has votes and unwithdrawed reward, selfdestruct will auto clear votes and withdraw allowance and reward to contract balance. There may be some rewards of current cycle that can never be withdrawed.