From 1139fed0098956f5d247e53584150acaf42f3dc7 Mon Sep 17 00:00:00 2001 From: kyriediculous Date: Fri, 16 Feb 2024 03:56:43 +0100 Subject: [PATCH 1/4] feat: staking precompile delegation and stakingpool queries --- precompiles/common/expected_keepers.go | 2 ++ precompiles/staking/Staking.sol | 31 ++++++++---------- precompiles/staking/staking.go | 44 ++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/precompiles/common/expected_keepers.go b/precompiles/common/expected_keepers.go index 8dae28f850..26e267b1e8 100644 --- a/precompiles/common/expected_keepers.go +++ b/precompiles/common/expected_keepers.go @@ -42,6 +42,8 @@ type StakingKeeper interface { Delegate(goCtx context.Context, msg *stakingtypes.MsgDelegate) (*stakingtypes.MsgDelegateResponse, error) BeginRedelegate(goCtx context.Context, msg *stakingtypes.MsgBeginRedelegate) (*stakingtypes.MsgBeginRedelegateResponse, error) Undelegate(goCtx context.Context, msg *stakingtypes.MsgUndelegate) (*stakingtypes.MsgUndelegateResponse, error) + Delegation(goCtx context.Context, delegatorAddr, validatorAddr string) (stakingtypes.QueryDelegationResponse, error) + Validator(goCtx context.Context, validatorAddr string) (stakingtypes.QueryValidatorResponse, error) } type GovKeeper interface { diff --git a/precompiles/staking/Staking.sol b/precompiles/staking/Staking.sol index 7d7fa50305..0bdbe30fb5 100644 --- a/precompiles/staking/Staking.sol +++ b/precompiles/staking/Staking.sol @@ -3,25 +3,22 @@ pragma solidity ^0.8.0; address constant STAKING_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001005; -IStaking constant STAKING_CONTRACT = IStaking( - STAKING_PRECOMPILE_ADDRESS -); +IStaking constant STAKING_CONTRACT = IStaking(STAKING_PRECOMPILE_ADDRESS); interface IStaking { // Transactions - function delegate( - string memory valAddress, - uint256 amount - ) external returns (bool success); + function delegate(string memory valAddress, uint256 amount) external returns (bool success); - function redelegate( - string memory srcAddress, - string memory dstAddress, - uint256 amount - ) external returns (bool success); + function redelegate(string memory srcAddress, string memory dstAddress, uint256 amount) + external + returns (bool success); - function undelegate( - string memory valAddress, - uint256 amount - ) external returns (bool success); -} \ No newline at end of file + function undelegate(string memory valAddress, uint256 amount) external returns (bool success); + + function getDelegation(address delegator, string memory valAddress) external view returns (uint256 shares); + + function getStakingPool(string memory valAddress) + external + view + returns (uint256 totalShares, uint256 totalTokens); +} diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 6f5eb78b49..449164bd29 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -17,6 +17,8 @@ const ( DelegateMethod = "delegate" RedelegateMethod = "redelegate" UndelegateMethod = "undelegate" + DelegationQuery = "getDelegation" + StakingPoolQuery = "getStakingPool" ) const ( @@ -49,9 +51,11 @@ type Precompile struct { evmKeeper pcommon.EVMKeeper address common.Address - DelegateID []byte - RedelegateID []byte - UndelegateID []byte + DelegateID []byte + RedelegateID []byte + UndelegateID []byte + DelegationID []byte + StakingPoolID []byte } func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKeeper) (*Precompile, error) { @@ -72,7 +76,12 @@ func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKee p.RedelegateID = m.ID case UndelegateMethod: p.UndelegateID = m.ID + case DelegationQuery: + p.DelegationID = m.ID + case StakingPoolQuery: + p.StakingPoolID = m.ID } + } return p, nil @@ -88,6 +97,10 @@ func (p Precompile) RequiredGas(input []byte) uint64 { return 70000 } else if bytes.Equal(methodID, p.UndelegateID) { return 50000 + } else if bytes.Equal(methodID, p.DelegationID) { + return 5000 + } else if bytes.Equal(methodID, p.StakingPoolID) { + return 5000 } panic("unknown method") } @@ -109,6 +122,10 @@ func (p Precompile) Run(evm *vm.EVM, caller common.Address, input []byte) (bz [] return p.redelegate(ctx, method, caller, args) case UndelegateMethod: return p.undelegate(ctx, method, caller, args) + case DelegationQuery: + return p.getDelegation(ctx, method, caller, args) + case StakingPoolQuery: + return p.getStakingPool(ctx, method, caller, args) } return } @@ -162,3 +179,24 @@ func (p Precompile) undelegate(ctx sdk.Context, method *abi.Method, caller commo } return method.Outputs.Pack(true) } + +func (p Precompile) getDelegation(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { + pcommon.AssertArgsLength(args, 2) + delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) + validatorBech32 := args[0].(string) + delegation, err := p.stakingKeeper.Delegation(sdk.WrapSDKContext(ctx), delegator.String(), validatorBech32) + if err != nil { + return nil, err + } + return method.Outputs.Pack(delegation.DelegationResponse.Balance) +} + +func (p Precompile) getStakingPool(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { + pcommon.AssertArgsLength(args, 1) + validatorBech32 := args[0].(string) + validator, err := p.stakingKeeper.Validator(sdk.WrapSDKContext(ctx), validatorBech32) + if err != nil { + return nil, err + } + return method.Outputs.Pack(validator.Validator.Tokens, validator.Validator.DelegatorShares) +} From 0cb705a2015ff7074a6b74e87c1cb198914a5aa2 Mon Sep 17 00:00:00 2001 From: kyriediculous Date: Fri, 22 Mar 2024 14:38:43 +0100 Subject: [PATCH 2/4] feat: improve undelegation precompiles --- go.mod | 6 +-- go.sum | 7 +-- precompiles/common/expected_keepers.go | 1 + precompiles/staking/Staking.sol | 36 ++++++++++--- precompiles/staking/staking.go | 70 +++++++++++++++++++------- 5 files changed, 85 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 0073b362bd..a22e9935fc 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/CosmWasm/wasmvm v1.0.1 github.com/armon/go-metrics v0.4.1 github.com/btcsuite/btcd v0.22.1 - github.com/cosmos/cosmos-sdk v0.45.10 + github.com/cosmos/cosmos-sdk v0.47.10 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.21.0-alpha.1.0.20230904092046-df3db2d96583 github.com/cosmos/ibc-go/v3 v3.0.0 @@ -125,7 +125,6 @@ require ( github.com/fzipp/gocyclo v0.5.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/go-critic/go-critic v0.6.3 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -173,7 +172,6 @@ require ( github.com/gostaticanalysis/nilerr v0.1.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect @@ -348,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.0.7 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.2.73-evm-rebase-8 + github.com/cosmos/cosmos-sdk => github.com/kyriediculous/sei-cosmos v0.0.0-20240322114009-4b53a028582c github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.0 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-8 diff --git a/go.sum b/go.sum index 2e8718fe8e..ec6a576ca5 100644 --- a/go.sum +++ b/go.sum @@ -457,7 +457,6 @@ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2Gihuqh github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -765,8 +764,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= @@ -956,6 +953,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/kyriediculous/sei-cosmos v0.0.0-20240322114009-4b53a028582c h1:jkGuvkSQSrHDWg8d/vLqttB11lpV7P5CcBFFyfr9yGQ= +github.com/kyriediculous/sei-cosmos v0.0.0-20240322114009-4b53a028582c/go.mod h1:9lxLcKzSw+dWguFY8JkE04O1OlEjKxHsuP5zK/pS8q0= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= @@ -1349,8 +1348,6 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-8 h1:z6rUvSgLXtXQBdF1dOe8A1iDFOR github.com/sei-protocol/go-ethereum v1.13.5-sei-8/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.2.73-evm-rebase-8 h1:ueyLkyzlvuInVIPKvd4FLqe/N8+wZSRtfh5C0RMi7rQ= -github.com/sei-protocol/sei-cosmos v0.2.73-evm-rebase-8/go.mod h1:xhbsd0d50m0pKrYkWluhCIkLOaqE8AlEROiaPr4VkXQ= github.com/sei-protocol/sei-db v0.0.30 h1:dlAOTE+7nByzzAD9cb1/DxaHWbxXOHFh58a2ImvcoYs= github.com/sei-protocol/sei-db v0.0.30/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= diff --git a/precompiles/common/expected_keepers.go b/precompiles/common/expected_keepers.go index 26e267b1e8..c73ddff04c 100644 --- a/precompiles/common/expected_keepers.go +++ b/precompiles/common/expected_keepers.go @@ -44,6 +44,7 @@ type StakingKeeper interface { Undelegate(goCtx context.Context, msg *stakingtypes.MsgUndelegate) (*stakingtypes.MsgUndelegateResponse, error) Delegation(goCtx context.Context, delegatorAddr, validatorAddr string) (stakingtypes.QueryDelegationResponse, error) Validator(goCtx context.Context, validatorAddr string) (stakingtypes.QueryValidatorResponse, error) + UnbondingDelegation(goCtx context.Context, delegatorAddr, validatorAddr string) (stakingtypes.QueryUnbondingDelegationResponse, error) } type GovKeeper interface { diff --git a/precompiles/staking/Staking.sol b/precompiles/staking/Staking.sol index 0bdbe30fb5..0b71afbf00 100644 --- a/precompiles/staking/Staking.sol +++ b/precompiles/staking/Staking.sol @@ -5,20 +5,40 @@ address constant STAKING_PRECOMPILE_ADDRESS = 0x00000000000000000000000000000000 IStaking constant STAKING_CONTRACT = IStaking(STAKING_PRECOMPILE_ADDRESS); +enum BondStatus { + Unbonded, + Unbonding, + Bonded +} + +struct UnbondingDelegation { + uint256 initialAmount; + uint256 amount; + uint256 creationHeight; + uint256 completionTime; +} + +struct StakingPool { + uint256 totalShares; + uint256 totalTokens; + BondStatus status; + bool jailed; +} + interface IStaking { // Transactions - function delegate(string memory valAddress, uint256 amount) external returns (bool success); + function delegate(address validator, uint256 amount) external returns (bool success); - function redelegate(string memory srcAddress, string memory dstAddress, uint256 amount) - external - returns (bool success); + function redelegate(address src, address dst, uint256 amount) external returns (bool success); + + function undelegate(address validator, uint256 amount) external returns (uint256 unbondingID); - function undelegate(string memory valAddress, uint256 amount) external returns (bool success); + function getDelegation(address delegator, address validator) external view returns (uint256 shares); - function getDelegation(address delegator, string memory valAddress) external view returns (uint256 shares); + function getStakingPool(address validator) external view returns (StakingPool memory); - function getStakingPool(string memory valAddress) + function getUnbondingDelegation(address validator, uint256 unbondingID) external view - returns (uint256 totalShares, uint256 totalTokens); + returns (UnbondingDelegation memory); } diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 449164bd29..40962b9a57 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -14,11 +14,12 @@ import ( ) const ( - DelegateMethod = "delegate" - RedelegateMethod = "redelegate" - UndelegateMethod = "undelegate" - DelegationQuery = "getDelegation" - StakingPoolQuery = "getStakingPool" + DelegateMethod = "delegate" + RedelegateMethod = "redelegate" + UndelegateMethod = "undelegate" + DelegationQuery = "getDelegation" + StakingPoolQuery = "getStakingPool" + UnbondingDelegationQuery = "getUnbondingDelegation" ) const ( @@ -51,11 +52,12 @@ type Precompile struct { evmKeeper pcommon.EVMKeeper address common.Address - DelegateID []byte - RedelegateID []byte - UndelegateID []byte - DelegationID []byte - StakingPoolID []byte + DelegateID []byte + RedelegateID []byte + UndelegateID []byte + DelegationID []byte + StakingPoolID []byte + UnbondingDelegationID []byte } func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKeeper) (*Precompile, error) { @@ -80,6 +82,8 @@ func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKee p.DelegationID = m.ID case StakingPoolQuery: p.StakingPoolID = m.ID + case UnbondingDelegationQuery: + p.UnbondingDelegationID = m.ID } } @@ -101,6 +105,8 @@ func (p Precompile) RequiredGas(input []byte) uint64 { return 5000 } else if bytes.Equal(methodID, p.StakingPoolID) { return 5000 + } else if bytes.Equal(methodID, p.UnbondingDelegationID) { + return 10000 } panic("unknown method") } @@ -126,6 +132,8 @@ func (p Precompile) Run(evm *vm.EVM, caller common.Address, input []byte) (bz [] return p.getDelegation(ctx, method, caller, args) case StakingPoolQuery: return p.getStakingPool(ctx, method, caller, args) + case UnbondingDelegationQuery: + return p.getUnbondingDelegation(ctx, method, caller, args) } return } @@ -133,7 +141,7 @@ func (p Precompile) Run(evm *vm.EVM, caller common.Address, input []byte) (bz [] func (p Precompile) delegate(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 2) delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) - validatorBech32 := args[0].(string) + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() amount := args[1].(*big.Int) _, err := p.stakingKeeper.Delegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgDelegate{ DelegatorAddress: delegator.String(), @@ -149,8 +157,8 @@ func (p Precompile) delegate(ctx sdk.Context, method *abi.Method, caller common. func (p Precompile) redelegate(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 3) delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) - srcValidatorBech32 := args[0].(string) - dstValidatorBech32 := args[1].(string) + srcValidatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() + dstValidatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[1].(common.Address)).String() amount := args[2].(*big.Int) _, err := p.stakingKeeper.BeginRedelegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgBeginRedelegate{ DelegatorAddress: delegator.String(), @@ -167,7 +175,7 @@ func (p Precompile) redelegate(ctx sdk.Context, method *abi.Method, caller commo func (p Precompile) undelegate(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 2) delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) - validatorBech32 := args[0].(string) + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() amount := args[1].(*big.Int) _, err := p.stakingKeeper.Undelegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgUndelegate{ DelegatorAddress: delegator.String(), @@ -177,13 +185,18 @@ func (p Precompile) undelegate(ctx sdk.Context, method *abi.Method, caller commo if err != nil { return nil, err } - return method.Outputs.Pack(true) + unbonds, err := p.stakingKeeper.UnbondingDelegation(sdk.WrapSDKContext(ctx), delegator.String(), validatorBech32) + if err != nil { + return nil, err + } + entry := unbonds.Unbond.Entries[len(unbonds.Unbond.Entries)-1] + return method.Outputs.Pack(entry.UnbondingId) } func (p Precompile) getDelegation(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 2) delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) - validatorBech32 := args[0].(string) + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() delegation, err := p.stakingKeeper.Delegation(sdk.WrapSDKContext(ctx), delegator.String(), validatorBech32) if err != nil { return nil, err @@ -193,10 +206,31 @@ func (p Precompile) getDelegation(ctx sdk.Context, method *abi.Method, caller co func (p Precompile) getStakingPool(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 1) - validatorBech32 := args[0].(string) + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() validator, err := p.stakingKeeper.Validator(sdk.WrapSDKContext(ctx), validatorBech32) if err != nil { return nil, err } - return method.Outputs.Pack(validator.Validator.Tokens, validator.Validator.DelegatorShares) + return method.Outputs.Pack(struct { + TotalShares *big.Int + TotalTokens *big.Int + Status stakingtypes.BondStatus + Jailed bool + }{ + validator.Validator.DelegatorShares.BigInt(), + validator.Validator.Tokens.BigInt(), + validator.Validator.Status, + validator.Validator.Jailed, + }) +} + +func (p Precompile) getUnbondingDelegation(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { + pcommon.AssertArgsLength(args, 2) + delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() + unbonding, err := p.stakingKeeper.UnbondingDelegation(sdk.WrapSDKContext(ctx), delegator.String(), validatorBech32) + if err != nil { + return nil, err + } + return method.Outputs.Pack(unbonding) } From 2632f152f85690771559a5ce6da96800c85f3b00 Mon Sep 17 00:00:00 2001 From: kyriediculous Date: Fri, 22 Mar 2024 23:34:43 +0100 Subject: [PATCH 3/4] fix: simplify delegate/undelegate --- go.mod | 2 +- go.sum | 4 ++-- precompiles/staking/Staking.sol | 5 +++-- precompiles/staking/staking.go | 13 ++++--------- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index a22e9935fc..4150a6b806 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.0.7 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/kyriediculous/sei-cosmos v0.0.0-20240322114009-4b53a028582c + github.com/cosmos/cosmos-sdk => github.com/kyriediculous/sei-cosmos v0.0.0-20240322222612-9e2a3f019263 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.0 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-8 diff --git a/go.sum b/go.sum index ec6a576ca5..a89987c008 100644 --- a/go.sum +++ b/go.sum @@ -953,8 +953,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= -github.com/kyriediculous/sei-cosmos v0.0.0-20240322114009-4b53a028582c h1:jkGuvkSQSrHDWg8d/vLqttB11lpV7P5CcBFFyfr9yGQ= -github.com/kyriediculous/sei-cosmos v0.0.0-20240322114009-4b53a028582c/go.mod h1:9lxLcKzSw+dWguFY8JkE04O1OlEjKxHsuP5zK/pS8q0= +github.com/kyriediculous/sei-cosmos v0.0.0-20240322222612-9e2a3f019263 h1:iTSOaJ2/s+6JDpEl+3QhFWzgFlvF0IoT2ZiNHtuo2fA= +github.com/kyriediculous/sei-cosmos v0.0.0-20240322222612-9e2a3f019263/go.mod h1:9lxLcKzSw+dWguFY8JkE04O1OlEjKxHsuP5zK/pS8q0= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= diff --git a/precompiles/staking/Staking.sol b/precompiles/staking/Staking.sol index 0b71afbf00..446b791059 100644 --- a/precompiles/staking/Staking.sol +++ b/precompiles/staking/Staking.sol @@ -26,13 +26,14 @@ struct StakingPool { } interface IStaking { - // Transactions - function delegate(address validator, uint256 amount) external returns (bool success); + // Messages + function delegate(address validator, uint256 amount) external returns (uint256 shares); function redelegate(address src, address dst, uint256 amount) external returns (bool success); function undelegate(address validator, uint256 amount) external returns (uint256 unbondingID); + // Queries function getDelegation(address delegator, address validator) external view returns (uint256 shares); function getStakingPool(address validator) external view returns (StakingPool memory); diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 40962b9a57..51238b254a 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -143,7 +143,7 @@ func (p Precompile) delegate(ctx sdk.Context, method *abi.Method, caller common. delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() amount := args[1].(*big.Int) - _, err := p.stakingKeeper.Delegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgDelegate{ + res, err := p.stakingKeeper.Delegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgDelegate{ DelegatorAddress: delegator.String(), ValidatorAddress: validatorBech32, Amount: sdk.NewCoin(p.evmKeeper.GetBaseDenom(ctx), sdk.NewIntFromBigInt(amount)), @@ -151,7 +151,7 @@ func (p Precompile) delegate(ctx sdk.Context, method *abi.Method, caller common. if err != nil { return nil, err } - return method.Outputs.Pack(true) + return method.Outputs.Pack(res.Shares) } func (p Precompile) redelegate(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { @@ -177,7 +177,7 @@ func (p Precompile) undelegate(ctx sdk.Context, method *abi.Method, caller commo delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() amount := args[1].(*big.Int) - _, err := p.stakingKeeper.Undelegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgUndelegate{ + res, err := p.stakingKeeper.Undelegate(sdk.WrapSDKContext(ctx), &stakingtypes.MsgUndelegate{ DelegatorAddress: delegator.String(), ValidatorAddress: validatorBech32, Amount: sdk.NewCoin(p.evmKeeper.GetBaseDenom(ctx), sdk.NewIntFromBigInt(amount)), @@ -185,12 +185,7 @@ func (p Precompile) undelegate(ctx sdk.Context, method *abi.Method, caller commo if err != nil { return nil, err } - unbonds, err := p.stakingKeeper.UnbondingDelegation(sdk.WrapSDKContext(ctx), delegator.String(), validatorBech32) - if err != nil { - return nil, err - } - entry := unbonds.Unbond.Entries[len(unbonds.Unbond.Entries)-1] - return method.Outputs.Pack(entry.UnbondingId) + return method.Outputs.Pack(res.UnbondingId) } func (p Precompile) getDelegation(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { From 8cc35f8e5f3eae1e7a1d77bcec5a0c4da6d31a8d Mon Sep 17 00:00:00 2001 From: kyriediculous Date: Sun, 24 Mar 2024 16:20:25 +0100 Subject: [PATCH 4/4] fix: get UnbondingDelegations for delegator/validator pair, and get UnbondingDelegation by ID --- go.mod | 2 +- precompiles/common/expected_keepers.go | 1 + precompiles/staking/Staking.sol | 11 +++-- precompiles/staking/staking.go | 59 +++++++++++++++++--------- 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 4150a6b806..06483f8877 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/CosmWasm/wasmvm v1.0.1 github.com/armon/go-metrics v0.4.1 github.com/btcsuite/btcd v0.22.1 - github.com/cosmos/cosmos-sdk v0.47.10 + github.com/cosmos/cosmos-sdk v0.45.10 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.21.0-alpha.1.0.20230904092046-df3db2d96583 github.com/cosmos/ibc-go/v3 v3.0.0 diff --git a/precompiles/common/expected_keepers.go b/precompiles/common/expected_keepers.go index c73ddff04c..7b234f581b 100644 --- a/precompiles/common/expected_keepers.go +++ b/precompiles/common/expected_keepers.go @@ -45,6 +45,7 @@ type StakingKeeper interface { Delegation(goCtx context.Context, delegatorAddr, validatorAddr string) (stakingtypes.QueryDelegationResponse, error) Validator(goCtx context.Context, validatorAddr string) (stakingtypes.QueryValidatorResponse, error) UnbondingDelegation(goCtx context.Context, delegatorAddr, validatorAddr string) (stakingtypes.QueryUnbondingDelegationResponse, error) + UnbondingDelegationByUnbondingId(goCtx context.Context, delegatorAddr, validatorAddr string, unbondingId uint64) (stakingtypes.UnbondingDelegationEntry, error) } type GovKeeper interface { diff --git a/precompiles/staking/Staking.sol b/precompiles/staking/Staking.sol index 446b791059..b0ea18a293 100644 --- a/precompiles/staking/Staking.sol +++ b/precompiles/staking/Staking.sol @@ -11,7 +11,7 @@ enum BondStatus { Bonded } -struct UnbondingDelegation { +struct UnbondingDelegationEntry { uint256 initialAmount; uint256 amount; uint256 creationHeight; @@ -38,8 +38,13 @@ interface IStaking { function getStakingPool(address validator) external view returns (StakingPool memory); - function getUnbondingDelegation(address validator, uint256 unbondingID) + function getUnbondingDelegationByUnbondingID(address delegator, address validator) external view - returns (UnbondingDelegation memory); + returns (UnbondingDelegationEntry[] memory); + + function getUnbondingDelegationByUnbondingID(address delegator, address validator, uint256 unbondingID) + external + view + returns (UnbondingDelegationEntry memory); } diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 51238b254a..ec7954e179 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -14,12 +14,13 @@ import ( ) const ( - DelegateMethod = "delegate" - RedelegateMethod = "redelegate" - UndelegateMethod = "undelegate" - DelegationQuery = "getDelegation" - StakingPoolQuery = "getStakingPool" - UnbondingDelegationQuery = "getUnbondingDelegation" + DelegateMethod = "delegate" + RedelegateMethod = "redelegate" + UndelegateMethod = "undelegate" + DelegationQuery = "getDelegation" + StakingPoolQuery = "getStakingPool" + UnbondingDelegationQuery = "getUnbondingDelegation" + UnbondingDelegationByUnbondingIDQuery = "getUnbondingDelegationByUnbondingId" ) const ( @@ -52,12 +53,13 @@ type Precompile struct { evmKeeper pcommon.EVMKeeper address common.Address - DelegateID []byte - RedelegateID []byte - UndelegateID []byte - DelegationID []byte - StakingPoolID []byte - UnbondingDelegationID []byte + DelegateID []byte + RedelegateID []byte + UndelegateID []byte + DelegationID []byte + StakingPoolID []byte + UnbondingDelegationID []byte + UnbondingDelegationByUnbondingID []byte } func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKeeper) (*Precompile, error) { @@ -84,6 +86,8 @@ func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKee p.StakingPoolID = m.ID case UnbondingDelegationQuery: p.UnbondingDelegationID = m.ID + case UnbondingDelegationByUnbondingIDQuery: + p.UnbondingDelegationByUnbondingID = m.ID } } @@ -131,11 +135,14 @@ func (p Precompile) Run(evm *vm.EVM, caller common.Address, input []byte) (bz [] case DelegationQuery: return p.getDelegation(ctx, method, caller, args) case StakingPoolQuery: - return p.getStakingPool(ctx, method, caller, args) + return p.getStakingPool(ctx, method, args) case UnbondingDelegationQuery: - return p.getUnbondingDelegation(ctx, method, caller, args) + return p.getUnbondingDelegation(ctx, method, args) + case UnbondingDelegationByUnbondingIDQuery: + return p.getUnbondingDelegationByUnbondingId(ctx, method, args) + default: + return } - return } func (p Precompile) delegate(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { @@ -199,7 +206,7 @@ func (p Precompile) getDelegation(ctx sdk.Context, method *abi.Method, caller co return method.Outputs.Pack(delegation.DelegationResponse.Balance) } -func (p Precompile) getStakingPool(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { +func (p Precompile) getStakingPool(ctx sdk.Context, method *abi.Method, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 1) validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() validator, err := p.stakingKeeper.Validator(sdk.WrapSDKContext(ctx), validatorBech32) @@ -219,13 +226,25 @@ func (p Precompile) getStakingPool(ctx sdk.Context, method *abi.Method, caller c }) } -func (p Precompile) getUnbondingDelegation(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}) ([]byte, error) { +func (p Precompile) getUnbondingDelegation(ctx sdk.Context, method *abi.Method, args []interface{}) ([]byte, error) { pcommon.AssertArgsLength(args, 2) - delegator := p.evmKeeper.GetSeiAddressOrDefault(ctx, caller) - validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() - unbonding, err := p.stakingKeeper.UnbondingDelegation(sdk.WrapSDKContext(ctx), delegator.String(), validatorBech32) + delegatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[1].(common.Address)).String() + unbonding, err := p.stakingKeeper.UnbondingDelegation(sdk.WrapSDKContext(ctx), delegatorBech32, validatorBech32) if err != nil { return nil, err } return method.Outputs.Pack(unbonding) } + +func (p Precompile) getUnbondingDelegationByUnbondingId(ctx sdk.Context, method *abi.Method, args []interface{}) ([]byte, error) { + pcommon.AssertArgsLength(args, 1) + delegatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[0].(common.Address)).String() + validatorBech32 := p.evmKeeper.GetSeiAddressOrDefault(ctx, args[1].(common.Address)).String() + unbondingId := args[2].(uint64) + unbondingEntry, err := p.stakingKeeper.UnbondingDelegationByUnbondingId(sdk.WrapSDKContext(ctx), delegatorBech32, validatorBech32, unbondingId) + if err != nil { + return nil, err + } + return method.Outputs.Pack(unbondingEntry) +}