feat: distribution precompile

This commit is contained in:
MiniFrenchBread 2025-03-06 19:52:15 +08:00
parent 351c2cb132
commit f2bd26e111
8 changed files with 1942 additions and 13 deletions

View File

@ -0,0 +1,523 @@
[
{
"inputs": [],
"name": "CommunityPool",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "pool",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatorAddress",
"type": "address"
},
{
"internalType": "address",
"name": "validatorAddress",
"type": "address"
}
],
"name": "delegationRewards",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "rewards",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatorAddress",
"type": "address"
}
],
"name": "delegationTotalRewards",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "validatorAddress",
"type": "address"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "reward",
"type": "tuple[]"
}
],
"internalType": "struct DelegationDelegatorReward[]",
"name": "rewards",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "total",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatorAddress",
"type": "address"
}
],
"name": "delegatorValidators",
"outputs": [
{
"internalType": "address[]",
"name": "validators",
"type": "address[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatorAddress",
"type": "address"
}
],
"name": "delegatorWithdrawAddress",
"outputs": [
{
"internalType": "address",
"name": "withdrawAddress",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "depositor",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "fundCommunityPool",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "params",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "communityTax",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "baseProposerReward",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "bonusProposerReward",
"type": "uint256"
},
{
"internalType": "bool",
"name": "withdrawAddrEnabled",
"type": "bool"
}
],
"internalType": "struct Params",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatorAddress",
"type": "address"
},
{
"internalType": "address",
"name": "withdrawerAddress",
"type": "address"
}
],
"name": "setWithdrawAddress",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "validatorAddress",
"type": "string"
}
],
"name": "validatorCommission",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "commission",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "validatorAddress",
"type": "address"
}
],
"name": "validatorDistributionInfo",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "operatorAddress",
"type": "address"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "selfBondRewards",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "commission",
"type": "tuple[]"
}
],
"internalType": "struct ValidatorDistributionInfoResponse",
"name": "distributionInfo",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "validatorAddress",
"type": "address"
}
],
"name": "validatorOutstandingRewards",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct DecCoin[]",
"name": "rewards",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "validatorAddress",
"type": "address"
},
{
"internalType": "uint64",
"name": "startingHeight",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "endingHeight",
"type": "uint64"
},
{
"components": [
{
"internalType": "bytes",
"name": "key",
"type": "bytes"
},
{
"internalType": "uint64",
"name": "offset",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "limit",
"type": "uint64"
},
{
"internalType": "bool",
"name": "countTotal",
"type": "bool"
},
{
"internalType": "bool",
"name": "reverse",
"type": "bool"
}
],
"internalType": "struct PageRequest",
"name": "pageRequest",
"type": "tuple"
}
],
"name": "validatorSlashes",
"outputs": [
{
"components": [
{
"internalType": "uint64",
"name": "validatorPeriod",
"type": "uint64"
},
{
"internalType": "uint256",
"name": "fraction",
"type": "uint256"
}
],
"internalType": "struct ValidatorSlashEvent[]",
"name": "slashes",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "bytes",
"name": "nextKey",
"type": "bytes"
},
{
"internalType": "uint64",
"name": "total",
"type": "uint64"
}
],
"internalType": "struct PageResponse",
"name": "pageResponse",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatorAddress",
"type": "address"
},
{
"internalType": "string",
"name": "validatorAddress",
"type": "string"
}
],
"name": "withdrawDelegatorRewards",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "amount",
"type": "tuple[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "validatorAddress",
"type": "address"
}
],
"name": "withdrawValidatorCommission",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "amount",
"type": "tuple[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,135 @@
package distribution
import (
"strings"
precompiles_common "github.com/0glabs/0g-chain/precompiles/common"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
)
const (
PrecompileAddress = "0x0000000000000000000000000000000000001003"
// tx
DistributionFunctionSetWithdrawAddress = "setWithdrawAddress"
DistributionFunctionWithdrawDelegatorRewards = "withdrawDelegatorRewards"
DistributionFunctionWithdrawValidatorCommission = "withdrawValidatorCommission"
DistributionFunctionFundCommunityPool = "fundCommunityPool"
// query
DistributionFunctionParams = "params"
DistributionFunctionValidatorDistributionInfo = "validatorDistributionInfo"
DistributionFunctionValidatorOutstandingRewards = "validatorOutstandingRewards"
DistributionFunctionValidatorCommission = "validatorCommission"
DistributionFunctionValidatorSlashes = "validatorSlashes"
DistributionFunctionDelegationRewards = "delegationRewards"
DistributionFunctionDelegationTotalRewards = "delegationTotalRewards"
DistributionFunctionDelegatorValidators = "delegatorValidators"
DistributionFunctionDelegatorWithdrawAddress = "delegatorWithdrawAddress"
DistributionFunctionCommunityPool = "CommunityPool"
)
var _ vm.PrecompiledContract = &DistributionPrecompile{}
var _ precompiles_common.PrecompileCommon = &DistributionPrecompile{}
type DistributionPrecompile struct {
abi abi.ABI
distributionKeeper distributionkeeper.Keeper
}
func NewDistributionPrecompile(distributionKeeper distributionkeeper.Keeper) (*DistributionPrecompile, error) {
abi, err := abi.JSON(strings.NewReader(DistributionABI))
if err != nil {
return nil, err
}
return &DistributionPrecompile{
abi: abi,
distributionKeeper: distributionKeeper,
}, nil
}
// Address implements vm.PrecompiledContract.
func (d *DistributionPrecompile) Address() common.Address {
return common.HexToAddress(PrecompileAddress)
}
// RequiredGas implements vm.PrecompiledContract.
func (d *DistributionPrecompile) RequiredGas(input []byte) uint64 {
return 0
}
func (d *DistributionPrecompile) Abi() *abi.ABI {
return &d.abi
}
func (d *DistributionPrecompile) IsTx(method string) bool {
switch method {
case DistributionFunctionSetWithdrawAddress,
DistributionFunctionWithdrawDelegatorRewards,
DistributionFunctionWithdrawValidatorCommission,
DistributionFunctionFundCommunityPool:
return true
default:
return false
}
}
func (d *DistributionPrecompile) KVGasConfig() storetypes.GasConfig {
return storetypes.KVGasConfig()
}
// Run implements vm.PrecompiledContract.
func (d *DistributionPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
ctx, stateDB, method, initialGas, args, err := precompiles_common.InitializePrecompileCall(d, evm, contract, readonly)
if err != nil {
return nil, err
}
var bz []byte
switch method.Name {
// queries
case DistributionFunctionParams:
bz, err = d.Params(ctx, evm, method, args)
case DistributionFunctionValidatorDistributionInfo:
bz, err = d.ValidatorDistributionInfo(ctx, evm, method, args)
case DistributionFunctionValidatorOutstandingRewards:
bz, err = d.ValidatorOutstankingRewards(ctx, evm, method, args)
case DistributionFunctionValidatorCommission:
bz, err = d.ValidatorCommission(ctx, evm, method, args)
case DistributionFunctionValidatorSlashes:
bz, err = d.ValidatorSlashes(ctx, evm, method, args)
case DistributionFunctionDelegationRewards:
bz, err = d.DelegationRewards(ctx, evm, method, args)
case DistributionFunctionDelegationTotalRewards:
bz, err = d.DelegationTotalRewards(ctx, evm, method, args)
case DistributionFunctionDelegatorValidators:
bz, err = d.DelegatorValidators(ctx, evm, method, args)
case DistributionFunctionDelegatorWithdrawAddress:
bz, err = d.DelegatorWithdrawAddress(ctx, evm, method, args)
case DistributionFunctionCommunityPool:
bz, err = d.CommunityPool(ctx, evm, method, args)
// txs
case DistributionFunctionSetWithdrawAddress:
bz, err = d.CreateValidator(ctx, evm, stateDB, contract, method, args)
case DistributionFunctionWithdrawDelegatorRewards:
bz, err = d.EditValidator(ctx, evm, stateDB, contract, method, args)
case DistributionFunctionWithdrawValidatorCommission:
bz, err = d.Delegate(ctx, evm, stateDB, contract, method, args)
case DistributionFunctionFundCommunityPool:
bz, err = d.BeginRedelegate(ctx, evm, stateDB, contract, method, args)
}
if err != nil {
return nil, err
}
cost := ctx.GasMeter().GasConsumed() - initialGas
if !contract.UseGas(cost) {
return nil, vm.ErrOutOfGas
}
return bz, nil
}

View File

@ -0,0 +1,172 @@
package distribution
import (
sdk "github.com/cosmos/cosmos-sdk/types"
distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/vm"
)
func (d *DistributionPrecompile) Params(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryParamsRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.Params(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertParams(response.Params))
}
func (d *DistributionPrecompile) ValidatorDistributionInfo(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorDistributionInfoRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.ValidatorDistributionInfo(ctx, req)
if err != nil {
return nil, err
}
res, err := convertValidatorDistributionInfoResponse(response)
if err != nil {
return nil, err
}
return method.Outputs.Pack(res)
}
func (d *DistributionPrecompile) ValidatorOutstankingRewards(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorOutstankingRewardsRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.ValidatorOutstandingRewards(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertValidatorOutstandingRewardsResponse(response))
}
func (d *DistributionPrecompile) ValidatorCommission(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorCommissionRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.ValidatorCommission(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertValidatorCommissionResponse(response))
}
func (d *DistributionPrecompile) ValidatorSlashes(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorSlashesRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.ValidatorSlashes(ctx, req)
if err != nil {
return nil, err
}
slashes := make([]ValidatorSlashEvent, len(response.Slashes))
for i, slash := range response.Slashes {
slashes[i] = convertValidatorSlashEvent(slash)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(slashes, paginationResult)
}
func (d *DistributionPrecompile) DelegationRewards(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegationRewardsRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.DelegationRewards(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertDelegationRewardsResponse(response))
}
func (d *DistributionPrecompile) DelegationTotalRewards(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegationTotalRewardsRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.DelegationTotalRewards(ctx, req)
if err != nil {
return nil, err
}
rewards, total, err := convertDelegationTotalRewardsResponse(response)
if err != nil {
return nil, err
}
return method.Outputs.Pack(rewards, total)
}
func (d *DistributionPrecompile) DelegatorValidators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegatorValidatorsRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.DelegatorValidators(ctx, req)
if err != nil {
return nil, err
}
validators, err := convertDelegatorValidatorsResponse(response)
if err != nil {
return nil, err
}
return method.Outputs.Pack(validators)
}
func (d *DistributionPrecompile) DelegatorWithdrawAddress(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegatorWithdrawAddressRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.DelegatorWithdrawAddress(ctx, req)
if err != nil {
return nil, err
}
withdrawAddress, err := convertWithdrawAddress(response.WithdrawAddress)
if err != nil {
return nil, err
}
return method.Outputs.Pack(withdrawAddress)
}
func (d *DistributionPrecompile) CommunityPool(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryCommunityPoolRequest(args)
if err != nil {
return nil, err
}
response, err := distributionkeeper.Querier{Keeper: d.distributionKeeper}.CommunityPool(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertCommunityPoolResponse(response))
}

View File

@ -0,0 +1,305 @@
package distribution
import (
"fmt"
"math/big"
precompiles_common "github.com/0glabs/0g-chain/precompiles/common"
github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/ethereum/go-ethereum/common"
)
// Coin is an auto generated low-level Go binding around an user-defined struct.
type Coin = struct {
Denom string `json:"denom"`
Amount *big.Int `json:"amount"`
}
// DecCoin is an auto generated low-level Go binding around an user-defined struct.
type DecCoin = struct {
Denom string `json:"denom"`
Amount *big.Int `json:"amount"`
}
// DelegationDelegatorReward is an auto generated low-level Go binding around an user-defined struct.
type DelegationDelegatorReward = struct {
ValidatorAddress common.Address `json:"validatorAddress"`
Reward []DecCoin `json:"reward"`
}
// PageRequest is an auto generated low-level Go binding around an user-defined struct.
type PageRequest = struct {
Key []byte `json:"key"`
Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"`
CountTotal bool `json:"countTotal"`
Reverse bool `json:"reverse"`
}
// PageResponse is an auto generated low-level Go binding around an user-defined struct.
type PageResponse = struct {
NextKey []byte `json:"nextKey"`
Total uint64 `json:"total"`
}
// Params is an auto generated low-level Go binding around an user-defined struct.
type Params = struct {
CommunityTax *big.Int `json:"communityTax"`
BaseProposerReward *big.Int `json:"baseProposerReward"`
BonusProposerReward *big.Int `json:"bonusProposerReward"`
WithdrawAddrEnabled bool `json:"withdrawAddrEnabled"`
}
// ValidatorDistributionInfoResponse is an auto generated low-level Go binding around an user-defined struct.
type ValidatorDistributionInfoResponse = struct {
OperatorAddress common.Address `json:"operatorAddress"`
SelfBondRewards []DecCoin `json:"selfBondRewards"`
Commission []DecCoin `json:"commission"`
}
// ValidatorSlashEvent is an auto generated low-level Go binding around an user-defined struct.
type ValidatorSlashEvent = struct {
ValidatorPeriod uint64 `json:"validatorPeriod"`
Fraction *big.Int `json:"fraction"`
}
func NewQueryParamsRequest(args []interface{}) (*distributiontypes.QueryParamsRequest, error) {
if len(args) != 0 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 0, len(args))
}
return &distributiontypes.QueryParamsRequest{}, nil
}
func convertParams(params distributiontypes.Params) Params {
return Params{
CommunityTax: params.CommunityTax.BigInt(),
BaseProposerReward: params.BaseProposerReward.BigInt(),
BonusProposerReward: params.BonusProposerReward.BigInt(),
WithdrawAddrEnabled: params.WithdrawAddrEnabled,
}
}
func NewQueryValidatorDistributionInfoRequest(args []interface{}) (*distributiontypes.QueryValidatorDistributionInfoRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
validator := args[0].(common.Address)
return &distributiontypes.QueryValidatorDistributionInfoRequest{
ValidatorAddress: sdk.ValAddress(validator.Bytes()).String(),
}, nil
}
func convertDecCoins(coins github_com_cosmos_cosmos_sdk_types.DecCoins) []DecCoin {
ans := make([]DecCoin, len(coins))
for i, coin := range coins {
ans[i] = DecCoin{
Denom: coin.Denom,
Amount: coin.Amount.TruncateInt().BigInt(),
}
}
return ans
}
func convertValidatorDistributionInfoResponse(response *distributiontypes.QueryValidatorDistributionInfoResponse) (ValidatorDistributionInfoResponse, error) {
operatorAddress, err := sdk.ValAddressFromBech32(response.OperatorAddress)
if err != nil {
return ValidatorDistributionInfoResponse{}, err
}
return ValidatorDistributionInfoResponse{
OperatorAddress: common.BytesToAddress(operatorAddress.Bytes()),
SelfBondRewards: convertDecCoins(response.SelfBondRewards),
Commission: convertDecCoins(response.Commission),
}, nil
}
func NewQueryValidatorOutstankingRewardsRequest(args []interface{}) (*distributiontypes.QueryValidatorOutstandingRewardsRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
validator := args[0].(common.Address)
return &distributiontypes.QueryValidatorOutstandingRewardsRequest{
ValidatorAddress: sdk.ValAddress(validator.Bytes()).String(),
}, nil
}
func convertValidatorOutstandingRewardsResponse(response *distributiontypes.QueryValidatorOutstandingRewardsResponse) []DecCoin {
return convertDecCoins(response.Rewards.Rewards)
}
func NewQueryValidatorCommissionRequest(args []interface{}) (*distributiontypes.QueryValidatorCommissionRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
validator := args[0].(common.Address)
return &distributiontypes.QueryValidatorCommissionRequest{
ValidatorAddress: sdk.ValAddress(validator.Bytes()).String(),
}, nil
}
func convertValidatorCommissionResponse(response *distributiontypes.QueryValidatorCommissionResponse) []DecCoin {
return convertDecCoins(response.Commission.Commission)
}
func convertQueryPageRequest(pagination PageRequest) *query.PageRequest {
return &query.PageRequest{
Key: pagination.Key,
Offset: pagination.Offset,
Limit: pagination.Limit,
CountTotal: pagination.CountTotal,
Reverse: pagination.Reverse,
}
}
func NewQueryValidatorSlashesRequest(args []interface{}) (*distributiontypes.QueryValidatorSlashesRequest, error) {
if len(args) != 4 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 4, len(args))
}
validator := args[0].(common.Address)
return &distributiontypes.QueryValidatorSlashesRequest{
ValidatorAddress: sdk.ValAddress(validator.Bytes()).String(),
StartingHeight: args[1].(uint64),
EndingHeight: args[2].(uint64),
Pagination: convertQueryPageRequest(args[3].(PageRequest)),
}, nil
}
func convertValidatorSlashEvent(slash distributiontypes.ValidatorSlashEvent) ValidatorSlashEvent {
return ValidatorSlashEvent{
ValidatorPeriod: slash.ValidatorPeriod,
Fraction: slash.Fraction.BigInt(),
}
}
func convertPageResponse(pagination *query.PageResponse) PageResponse {
if pagination == nil {
return PageResponse{
NextKey: make([]byte, 0),
Total: 1,
}
}
return PageResponse{
NextKey: pagination.NextKey,
Total: pagination.Total,
}
}
func NewQueryDelegationRewardsRequest(args []interface{}) (*distributiontypes.QueryDelegationRewardsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegator := args[0].(common.Address)
validator := args[1].(common.Address)
return &distributiontypes.QueryDelegationRewardsRequest{
DelegatorAddress: sdk.AccAddress(delegator.Bytes()).String(),
ValidatorAddress: sdk.ValAddress(validator.Bytes()).String(),
}, nil
}
func convertDelegationRewardsResponse(response *distributiontypes.QueryDelegationRewardsResponse) []DecCoin {
return convertDecCoins(response.Rewards)
}
func NewQueryDelegationTotalRewardsRequest(args []interface{}) (*distributiontypes.QueryDelegationTotalRewardsRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
delegator := args[0].(common.Address)
return &distributiontypes.QueryDelegationTotalRewardsRequest{
DelegatorAddress: sdk.AccAddress(delegator.Bytes()).String(),
}, nil
}
func convertDelegationDelegatorReward(reward distributiontypes.DelegationDelegatorReward) (DelegationDelegatorReward, error) {
validatorAddress, err := sdk.ValAddressFromBech32(reward.ValidatorAddress)
if err != nil {
return DelegationDelegatorReward{}, err
}
return DelegationDelegatorReward{
ValidatorAddress: common.BytesToAddress(validatorAddress.Bytes()),
Reward: convertDecCoins(reward.Reward),
}, nil
}
func convertDelegationTotalRewardsResponse(response *distributiontypes.QueryDelegationTotalRewardsResponse) ([]DelegationDelegatorReward, []DecCoin, error) {
rewards := make([]DelegationDelegatorReward, len(response.Rewards))
var err error
for i, reward := range response.Rewards {
rewards[i], err = convertDelegationDelegatorReward(reward)
if err != nil {
return nil, nil, err
}
}
return rewards, convertDecCoins(response.Total), nil
}
func NewQueryDelegatorValidatorsRequest(args []interface{}) (*distributiontypes.QueryDelegatorValidatorsRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
delegator := args[0].(common.Address)
return &distributiontypes.QueryDelegatorValidatorsRequest{
DelegatorAddress: sdk.AccAddress(delegator.Bytes()).String(),
}, nil
}
func convertDelegatorValidatorsResponse(response *distributiontypes.QueryDelegatorValidatorsResponse) ([]common.Address, error) {
validators := make([]common.Address, len(response.Validators))
for i, addr := range response.Validators {
validatorAddress, err := sdk.ValAddressFromBech32(addr)
if err != nil {
return nil, err
}
validators[i] = common.BytesToAddress(validatorAddress.Bytes())
}
return validators, nil
}
func NewQueryDelegatorWithdrawAddressRequest(args []interface{}) (*distributiontypes.QueryDelegatorWithdrawAddressRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
delegator := args[0].(common.Address)
return &distributiontypes.QueryDelegatorWithdrawAddressRequest{
DelegatorAddress: sdk.AccAddress(delegator.Bytes()).String(),
}, nil
}
func convertWithdrawAddress(addr string) (common.Address, error) {
withdrawAddress, err := sdk.AccAddressFromBech32(addr)
if err != nil {
return common.Address{}, err
}
return common.Address(withdrawAddress.Bytes()), nil
}
func NewQueryCommunityPoolRequest(args []interface{}) (*distributiontypes.QueryCommunityPoolRequest, error) {
if len(args) != 0 {
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 0, len(args))
}
return &distributiontypes.QueryCommunityPoolRequest{}, nil
}
func convertCommunityPoolResponse(response *distributiontypes.QueryCommunityPoolResponse) []DecCoin {
return convertDecCoins(response.Pool)
}

View File

@ -0,0 +1,165 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;
import "./types.sol";
struct Params {
uint communityTax;
uint baseProposerReward;
uint bonusProposerReward;
bool withdrawAddrEnabled;
}
struct ValidatorDistributionInfoResponse {
address operatorAddress;
DecCoin[] selfBondRewards;
DecCoin[] commission;
}
struct ValidatorSlashEvent {
uint64 validatorPeriod;
uint fraction; // 18 decimals
}
struct DelegationDelegatorReward {
address validatorAddress;
DecCoin[] reward;
}
interface IDistribution {
/*=== events ===*/
/*=== cosmos tx ===*/
/**
* @dev SetWithdrawAddress defines a method to change the withdraw address for a delegator (or validator self-delegation).
* cosmos grpc: rpc SetWithdrawAddress(MsgSetWithdrawAddress) returns (MsgSetWithdrawAddressResponse);
*/
function setWithdrawAddress(
address delegatorAddress,
address withdrawerAddress
) external returns (bool success);
/**
* @dev WithdrawDelegatorReward defines a method to withdraw rewards of delegator from a single validator.
* cosmos grpc: rpc WithdrawDelegatorReward(MsgWithdrawDelegatorReward) returns (MsgWithdrawDelegatorRewardResponse);
*/
function withdrawDelegatorRewards(
address delegatorAddress,
string memory validatorAddress
) external returns (Coin[] calldata amount);
/**
* @dev WithdrawValidatorCommission defines a method to withdraw the full commission to the validator address.
* cosmos grpc: rpc WithdrawValidatorCommission(MsgWithdrawValidatorCommission) returns (MsgWithdrawValidatorCommissionResponse);
*/
function withdrawValidatorCommission(
address validatorAddress
) external returns (Coin[] calldata amount);
/**
* @dev FundCommunityPool defines a method to allow an account to directly fund the community pool.
* cosmos grpc: rpc FundCommunityPool(MsgFundCommunityPool) returns (MsgFundCommunityPoolResponse);
*/
function fundCommunityPool(
address depositor,
uint256 amount
) external returns (bool success);
/*=== cosmos query ===*/
/**
* @dev Params queries params of the distribution module.
* cosmos grpc: rpc Params(QueryParamsRequest) returns (QueryParamsResponse);
*/
function params() external view returns (Params memory);
/**
* @dev ValidatorDistributionInfo queries validator commission and self-delegation rewards for validator
* cosmos grpc: rpc ValidatorDistributionInfo(QueryValidatorDistributionInfoRequest) returns (QueryValidatorDistributionInfoResponse);
*/
function validatorDistributionInfo(
address validatorAddress
)
external
view
returns (ValidatorDistributionInfoResponse memory distributionInfo);
/**
* @dev ValidatorOutstandingRewards queries rewards of a validator address.
* cosmos grpc: rpc ValidatorOutstandingRewards(QueryValidatorOutstandingRewardsRequest) returns (QueryValidatorOutstandingRewardsResponse);
*/
function validatorOutstandingRewards(
address validatorAddress
) external view returns (DecCoin[] memory rewards);
/**
* @dev ValidatorCommission queries accumulated commission for a validator.
* cosmos grpc: rpc ValidatorCommission(QueryValidatorCommissionRequest) returns (QueryValidatorCommissionResponse);
*/
function validatorCommission(
string memory validatorAddress
) external view returns (DecCoin[] memory commission);
/**
* @dev ValidatorSlashes queries slash events of a validator.
* cosmos grpc: rpc ValidatorSlashes(QueryValidatorSlashesRequest) returns (QueryValidatorSlashesResponse);
*/
function validatorSlashes(
address validatorAddress,
uint64 startingHeight,
uint64 endingHeight,
PageRequest calldata pageRequest
)
external
view
returns (
ValidatorSlashEvent[] memory slashes,
PageResponse calldata pageResponse
);
/**
* @dev DelegationRewards queries the total rewards accrued by a delegation.
* cosmos grpc: rpc DelegationRewards(QueryDelegationRewardsRequest) returns (QueryDelegationRewardsResponse);
*/
function delegationRewards(
address delegatorAddress,
address validatorAddress
) external view returns (DecCoin[] memory rewards);
/**
* @dev DelegationTotalRewards queries the total rewards accrued by a each validator.
* cosmos grpc: rpc DelegationTotalRewards(QueryDelegationTotalRewardsRequest) returns (QueryDelegationTotalRewardsResponse);
*/
function delegationTotalRewards(
address delegatorAddress
)
external
view
returns (
DelegationDelegatorReward[] memory rewards,
DecCoin[] memory total
);
/**
* @dev DelegatorValidators queries the validators of a delegator.
* cosmos grpc: rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse);
*/
function delegatorValidators(
address delegatorAddress
) external view returns (address[] memory validators);
/**
* @dev DelegatorWithdrawAddress queries withdraw address of a delegator.
* cosmos grpc: rpc DelegatorWithdrawAddress(QueryDelegatorWithdrawAddressRequest) returns (QueryDelegatorWithdrawAddressResponse);
*/
function delegatorWithdrawAddress(
address delegatorAddress
) external view returns (address withdrawAddress);
/**
* @dev CommunityPool queries the community pool coins.
* cosmos grpc: rpc CommunityPool(QueryCommunityPoolRequest) returns (QueryCommunityPoolResponse);
*/
function CommunityPool() external view returns (DecCoin[] memory pool);
}

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;
import "./types.sol";
/**
* @dev Description defines a validator description
*/
@ -160,19 +162,6 @@ struct NullableUint {
uint value;
}
struct PageRequest {
bytes key;
uint64 offset;
uint64 limit;
bool countTotal;
bool reverse;
}
struct PageResponse {
bytes nextKey;
uint64 total;
}
interface IStaking {
/*=== cosmos tx ===*/

View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;
/**
* @dev cosmos.base.v1beta1.Coin
*/
struct Coin {
string denom;
uint amount;
}
/**
* @dev cosmos.base.v1beta1.DecCoin
* 18 decimals
*/
struct DecCoin {
string denom;
uint amount;
}
/**
* @dev cosmos.base.query.v1beta1.PageRequest
*/
struct PageRequest {
bytes key;
uint64 offset;
uint64 limit;
bool countTotal;
bool reverse;
}
/**
* @dev cosmos.base.query.v1beta1.PageResponse
*/
struct PageResponse {
bytes nextKey;
uint64 total;
}