Skip to content

Commit

Permalink
Add delegation and static call check (sei-protocol#1761)
Browse files Browse the repository at this point in the history
* add delegation and static call check

* retrigger checks
  • Loading branch information
dssei authored Jul 10, 2024
1 parent 1a93da3 commit cc0d48e
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 15 deletions.
6 changes: 6 additions & 0 deletions precompiles/distribution/distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ func NewPrecompile(distrKeeper pcommon.DistributionKeeper, evmKeeper pcommon.EVM
}

func (p PrecompileExecutor) Execute(ctx sdk.Context, method *abi.Method, caller common.Address, callingContract common.Address, args []interface{}, value *big.Int, readOnly bool, evm *vm.EVM, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
if readOnly {
return nil, 0, errors.New("cannot call distr precompile from staticcall")
}
if caller.Cmp(callingContract) != 0 {
return nil, 0, errors.New("cannot delegatecall distr")
}
switch method.Name {
case SetWithdrawAddressMethod:
return p.setWithdrawAddress(ctx, method, caller, args, value)
Expand Down
167 changes: 152 additions & 15 deletions precompiles/distribution/distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ func setupValidator(t *testing.T, ctx sdk.Context, a *app.App, bondStatus stakin

func TestPrecompile_RunAndCalculateGas_WithdrawDelegationRewards(t *testing.T) {
_, notAssociatedCallerEvmAddress := testkeeper.MockAddressPair()
_, contractEvmAddress := testkeeper.MockAddressPair()
validatorAddress := "seivaloper1reedlc9w8p7jrpqfky4c5k90nea4p6dhk5yqgd"

type fields struct {
Expand All @@ -364,6 +365,7 @@ func TestPrecompile_RunAndCalculateGas_WithdrawDelegationRewards(t *testing.T) {
validator string
suppliedGas uint64
value *big.Int
readOnly bool
}
tests := []struct {
name string
Expand Down Expand Up @@ -402,9 +404,10 @@ func TestPrecompile_RunAndCalculateGas_WithdrawDelegationRewards(t *testing.T) {
name: "fails if delegator is not associated",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
validator: validatorAddress,
suppliedGas: uint64(1000000),
caller: notAssociatedCallerEvmAddress,
callingContract: notAssociatedCallerEvmAddress,
validator: validatorAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
Expand All @@ -420,6 +423,49 @@ func TestPrecompile_RunAndCalculateGas_WithdrawDelegationRewards(t *testing.T) {
wantErr: true,
wantErrMsg: "{ReadFlat}",
},
{
name: "fails if caller != callingContract",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
callingContract: contractEvmAddress,
validator: validatorAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot delegatecall distr",
},
{
name: "fails if caller != callingContract and callingContract not set",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
callingContract: contractEvmAddress,
validator: validatorAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot delegatecall distr",
},
{
name: "fails if readOnly",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
callingContract: notAssociatedCallerEvmAddress,
validator: validatorAddress,
suppliedGas: uint64(1000000),
readOnly: true,
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot call distr precompile from staticcall",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -435,7 +481,7 @@ func TestPrecompile_RunAndCalculateGas_WithdrawDelegationRewards(t *testing.T) {
require.Nil(t, err)
inputs, err := withdraw.Inputs.Pack(tt.args.validator)
require.Nil(t, err)
gotRet, gotRemainingGas, err := p.RunAndCalculateGas(&evm, tt.args.caller, tt.args.callingContract, append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawDelegationRewardsID, inputs...), tt.args.suppliedGas, tt.args.value, nil, false)
gotRet, gotRemainingGas, err := p.RunAndCalculateGas(&evm, tt.args.caller, tt.args.callingContract, append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawDelegationRewardsID, inputs...), tt.args.suppliedGas, tt.args.value, nil, tt.args.readOnly)
if (err != nil) != tt.wantErr {
t.Errorf("RunAndCalculateGas() error = %v, wantErr %v", err, tt.wantErr)
return
Expand All @@ -455,6 +501,7 @@ func TestPrecompile_RunAndCalculateGas_WithdrawDelegationRewards(t *testing.T) {

func TestPrecompile_RunAndCalculateGas_WithdrawMultipleDelegationRewards(t *testing.T) {
_, notAssociatedCallerEvmAddress := testkeeper.MockAddressPair()
_, contractEvmAddress := testkeeper.MockAddressPair()
validatorAddresses := []string{"seivaloper1reedlc9w8p7jrpqfky4c5k90nea4p6dhk5yqgd"}

type fields struct {
Expand All @@ -473,6 +520,7 @@ func TestPrecompile_RunAndCalculateGas_WithdrawMultipleDelegationRewards(t *test
validators []string
suppliedGas uint64
value *big.Int
readOnly bool
}
tests := []struct {
name string
Expand Down Expand Up @@ -511,9 +559,10 @@ func TestPrecompile_RunAndCalculateGas_WithdrawMultipleDelegationRewards(t *test
name: "fails if delegator is not associated",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
validators: validatorAddresses,
suppliedGas: uint64(1000000),
caller: notAssociatedCallerEvmAddress,
callingContract: notAssociatedCallerEvmAddress,
validators: validatorAddresses,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
Expand All @@ -529,6 +578,48 @@ func TestPrecompile_RunAndCalculateGas_WithdrawMultipleDelegationRewards(t *test
wantErr: true,
wantErrMsg: "{ReadFlat}",
},
{
name: "fails if caller != callingContract",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
callingContract: contractEvmAddress,
validators: validatorAddresses,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot delegatecall distr",
},
{
name: "fails if caller != callingContract and callingContract not set",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
validators: validatorAddresses,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot delegatecall distr",
},
{
name: "fails if readOnly",
fields: fields{},
args: args{
caller: notAssociatedCallerEvmAddress,
callingContract: notAssociatedCallerEvmAddress,
validators: validatorAddresses,
suppliedGas: uint64(1000000),
readOnly: true,
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot call distr precompile from staticcall",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -544,7 +635,7 @@ func TestPrecompile_RunAndCalculateGas_WithdrawMultipleDelegationRewards(t *test
require.Nil(t, err)
inputs, err := withdraw.Inputs.Pack(tt.args.validators)
require.Nil(t, err)
gotRet, gotRemainingGas, err := p.RunAndCalculateGas(&evm, tt.args.caller, tt.args.callingContract, append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawMultipleDelegationRewardsID, inputs...), tt.args.suppliedGas, tt.args.value, nil, false)
gotRet, gotRemainingGas, err := p.RunAndCalculateGas(&evm, tt.args.caller, tt.args.callingContract, append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawMultipleDelegationRewardsID, inputs...), tt.args.suppliedGas, tt.args.value, nil, tt.args.readOnly)
if (err != nil) != tt.wantErr {
t.Errorf("RunAndCalculateGas() error = %v, wantErr %v", err, tt.wantErr)
return
Expand All @@ -565,6 +656,7 @@ func TestPrecompile_RunAndCalculateGas_WithdrawMultipleDelegationRewards(t *test
func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
_, notAssociatedCallerEvmAddress := testkeeper.MockAddressPair()
callerSeiAddress, callerEvmAddress := testkeeper.MockAddressPair()
_, contactEvmAddress := testkeeper.MockAddressPair()

type fields struct {
Precompile pcommon.Precompile
Expand All @@ -582,6 +674,7 @@ func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
callingContract common.Address
suppliedGas uint64
value *big.Int
readOnly bool
}
tests := []struct {
name string
Expand Down Expand Up @@ -620,9 +713,10 @@ func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
name: "fails if delegator is not associated",
fields: fields{},
args: args{
addressToSet: notAssociatedCallerEvmAddress,
caller: notAssociatedCallerEvmAddress,
suppliedGas: uint64(1000000),
addressToSet: notAssociatedCallerEvmAddress,
caller: notAssociatedCallerEvmAddress,
callingContract: notAssociatedCallerEvmAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
Expand All @@ -633,9 +727,10 @@ func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
name: "fails if address is invalid",
fields: fields{},
args: args{
addressToSet: common.Address{},
caller: callerEvmAddress,
suppliedGas: uint64(1000000),
addressToSet: common.Address{},
caller: callerEvmAddress,
callingContract: callerEvmAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
Expand All @@ -651,6 +746,48 @@ func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
wantErr: true,
wantErrMsg: "{ReadFlat}",
},
{
name: "fails if caller != callingContract",
fields: fields{},
args: args{
addressToSet: common.Address{},
caller: callerEvmAddress,
callingContract: contactEvmAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot delegatecall distr",
},
{
name: "fails if caller != callingContract with callingContract not set",
fields: fields{},
args: args{
addressToSet: common.Address{},
caller: callerEvmAddress,
suppliedGas: uint64(1000000),
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot delegatecall distr",
},
{
name: "fails if readOnly",
fields: fields{},
args: args{
addressToSet: common.Address{},
caller: callerEvmAddress,
callingContract: callerEvmAddress,
suppliedGas: uint64(1000000),
readOnly: true,
},
wantRet: nil,
wantRemainingGas: 0,
wantErr: true,
wantErrMsg: "cannot call distr precompile from staticcall",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -668,7 +805,7 @@ func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
require.Nil(t, err)
inputs, err := setAddress.Inputs.Pack(tt.args.addressToSet)
require.Nil(t, err)
gotRet, gotRemainingGas, err := p.RunAndCalculateGas(&evm, tt.args.caller, tt.args.callingContract, append(p.GetExecutor().(*distribution.PrecompileExecutor).SetWithdrawAddrID, inputs...), tt.args.suppliedGas, tt.args.value, nil, false)
gotRet, gotRemainingGas, err := p.RunAndCalculateGas(&evm, tt.args.caller, tt.args.callingContract, append(p.GetExecutor().(*distribution.PrecompileExecutor).SetWithdrawAddrID, inputs...), tt.args.suppliedGas, tt.args.value, nil, tt.args.readOnly)
if (err != nil) != tt.wantErr {
t.Errorf("RunAndCalculateGas() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down

0 comments on commit cc0d48e

Please sign in to comment.