-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(oracle): update params #83
Changes from 12 commits
81e0ef3
d1ffd59
3f76f0b
62529fd
d1ac7e2
3dbec4b
ebbd424
4f1acf2
ce11543
bf6d912
834861a
1e32628
02529bd
857a1be
4ed528f
e1b1e5b
e9eb65b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package cli | ||
|
||
import ( | ||
"github.com/ExocoreNetwork/exocore/x/oracle/types" | ||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
"github.com/cosmos/cosmos-sdk/client/tx" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func CmdUpdateParams() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
// TODO: support v1 single sourceID for temporary | ||
Use: "update-params params", | ||
Short: "Broadcast message update-params", | ||
Args: cobra.MinimumNArgs(1), | ||
RunE: func(cmd *cobra.Command, args []string) (err error) { | ||
clientCtx, err := client.GetClientTxContext(cmd) | ||
if err != nil { | ||
return err | ||
} | ||
msg := types.NewMsgUpdateParams(clientCtx.GetFromAddress().String(), args[0]) | ||
if err := msg.ValidateBasic(); err != nil { | ||
return err | ||
} | ||
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) | ||
}, | ||
} | ||
|
||
flags.AddTxFlagsToCmd(cmd) | ||
|
||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package keeper_test | ||
|
||
import ( | ||
"github.com/ExocoreNetwork/exocore/x/oracle/types" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("MsgUpdateParams", func() { | ||
var defaultParams types.Params | ||
BeforeEach(func() { | ||
ks.Reset() | ||
Expect(ks.ms).ToNot(BeNil()) | ||
defaultParams = ks.k.GetParams(ks.ctx) | ||
}) | ||
|
||
Context("Update Chains", func() { | ||
inputAddChains := []string{ | ||
`{"chains":[{"name":"Bitcoin", "desc":"-"}]}`, | ||
`{"chains":[{"name":"Ethereum", "desc":"-"}]}`, | ||
} | ||
It("add chain with new name", func() { | ||
msg := types.NewMsgUpdateParams("", inputAddChains[0]) | ||
_, err := ks.ms.UpdateParams(ks.ctx, msg) | ||
Expect(err).Should(BeNil()) | ||
p := ks.k.GetParams(ks.ctx) | ||
Expect(p.Chains[2].Name).Should(BeEquivalentTo("Bitcoin")) | ||
|
||
}) | ||
It("add chain with duplicated name", func() { | ||
_, err := ks.ms.UpdateParams(ks.ctx, types.NewMsgUpdateParams("", inputAddChains[1])) | ||
Expect(err).Should(MatchError(types.ErrInvalidParams.Wrap("invalid source to add, duplicated"))) | ||
}) | ||
}) | ||
Context("Update Sources", func() { | ||
inputAddSources := []string{ | ||
`{"sources":[{"name":"CoinGecko", "desc":"-", "valid":true}]}`, | ||
`{"sources":[{"name":"CoinGecko", "desc":"-"}]}`, | ||
`{"sources":[{"name":"Chainlink", "desc":"-", "valid":true}]}`, | ||
} | ||
It("add valid source with new name", func() { | ||
_, err := ks.ms.UpdateParams(ks.ctx, types.NewMsgUpdateParams("", inputAddSources[0])) | ||
Expect(err).Should(BeNil()) | ||
p := ks.k.GetParams(ks.ctx) | ||
Expect(p.Sources[2].Name).Should(BeEquivalentTo("CoinGecko")) | ||
}) | ||
It("add invalid source with new name", func() { | ||
_, err := ks.ms.UpdateParams(ks.ctx, types.NewMsgUpdateParams("", inputAddSources[1])) | ||
Expect(err).Should(MatchError(types.ErrInvalidParams.Wrap("invalid source to add, new source should be valid"))) | ||
}) | ||
It("add source with duplicated name", func() { | ||
_, err := ks.ms.UpdateParams(ks.ctx, types.NewMsgUpdateParams("", inputAddSources[2])) | ||
Expect(err).Should(MatchError(types.ErrInvalidParams.Wrap("invalid source to add, duplicated"))) | ||
}) | ||
}) | ||
Context("Update Tokens", func() { | ||
startBasedBlocks := []uint64{1, 3, 3, 3, 1, 1, 1} | ||
inputUpdateTokens := []string{ | ||
`{"tokens":[{"name":"UNI", "chain_id":"1"}]}`, | ||
`{"tokens":[{"name":"ETH", "chain_id":"1", "decimal":8}]}`, | ||
`{"tokens":[{"name":"ETH", "chain_id":"1", "asset_id":"assetID"}]}`, | ||
`{"tokens":[{"name":"ETH", "chain_id":"1", "contract_address":"contractAddress"}]}`, | ||
`{"tokens":[{"name":"ETH", "chain_id":"1", "decimal":8}]}`, | ||
`{"tokens":[{"name":"ETH", "chain_id":"0"}]}`, | ||
`{"tokens":[{"name":"ETH", "chain_id":"3"}]}`, | ||
} | ||
errs := []error{ | ||
nil, | ||
nil, | ||
nil, | ||
nil, | ||
nil, | ||
types.ErrInvalidParams.Wrap("invalid token to add, chain not found"), | ||
types.ErrInvalidParams.Wrap("invalid token to add, chain not found"), | ||
} | ||
token := types.DefaultParams().Tokens[1] | ||
token1 := *token | ||
token1.Decimal = 8 | ||
|
||
token2 := *token | ||
token2.AssetID = "assetID" | ||
|
||
token3 := *token | ||
token3.ContractAddress = "0x123" | ||
|
||
updatedTokenETH := []*types.Token{ | ||
nil, | ||
&token1, | ||
&token2, | ||
&token3, | ||
token, | ||
nil, | ||
nil, | ||
} | ||
|
||
for i, input := range inputUpdateTokens { | ||
It("", func() { //}) | ||
if startBasedBlocks[i] > 1 { | ||
p := defaultParams | ||
p.TokenFeeders[1].StartBaseBlock = startBasedBlocks[i] | ||
ks.k.SetParams(ks.ctx, p) | ||
} | ||
_, err := ks.ms.UpdateParams(ks.ctx, types.NewMsgUpdateParams("", input)) | ||
if errs[i] == nil { | ||
Expect(err).Should(BeNil()) | ||
} else { | ||
Expect(err).Should(MatchError(errs[i])) | ||
} | ||
if updatedTokenETH[i] != nil { | ||
p := ks.k.GetParams(ks.ctx) | ||
Expect(p.Tokens[1]).Should(BeEquivalentTo(updatedTokenETH[i])) | ||
} | ||
}) | ||
} | ||
|
||
}) | ||
|
||
Context("", func() { | ||
It("update StartBaseBlock for TokenFeeder", func() { | ||
p := defaultParams | ||
p.TokenFeeders[1].StartBaseBlock = 10 | ||
ks.k.SetParams(ks.ctx, p) | ||
p.TokenFeeders[1].StartBaseBlock = 5 | ||
_, err := ks.ms.UpdateParams(ks.ctx, &types.MsgUpdateParams{ | ||
Params: types.Params{ | ||
TokenFeeders: []*types.TokenFeeder{ | ||
{ | ||
TokenID: 1, | ||
StartBaseBlock: 5, | ||
}, | ||
}, | ||
}, | ||
}) | ||
Expect(err).Should(BeNil()) | ||
p = ks.k.GetParams(ks.ctx) | ||
Expect(p.TokenFeeders[1].StartBaseBlock).Should(BeEquivalentTo(5)) | ||
}) | ||
It("Add AssetID for Token", func() { | ||
_, err := ks.ms.UpdateParams(ks.ctx, &types.MsgUpdateParams{ | ||
Params: types.Params{ | ||
Tokens: []*types.Token{ | ||
{ | ||
Name: "ETH", | ||
ChainID: 1, | ||
AssetID: "0x83e6850591425e3c1e263c054f4466838b9bd9e4_0x9ce1", | ||
}, | ||
}, | ||
}, | ||
}) | ||
Expect(err).Should(BeNil()) | ||
p := ks.k.GetParams(ks.ctx) | ||
Expect(p.Tokens[1].AssetID).Should(BeEquivalentTo("0x83e6850591425e3c1e263c054f4466838b9bd9e4_0x9ce1")) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,3 +16,117 @@ func TestGetParams(t *testing.T) { | |
|
||
require.EqualValues(t, params, k.GetParams(ctx)) | ||
} | ||
|
||
func TestUpdateTokenFeeder(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
tokenFeeder types.TokenFeeder | ||
height uint64 | ||
err error | ||
}{ | ||
// fail when add/update fields, before validation | ||
{ | ||
name: "invalid update, empty fields to update", | ||
tokenFeeder: types.TokenFeeder{ | ||
TokenID: 1, | ||
}, | ||
height: 1, | ||
err: types.ErrInvalidParams.Wrap("invalid tokenFeeder to update, no valid field set"), | ||
}, | ||
{ | ||
name: "invalid udpate, for not-start feeder, set StartbaseBlock to history height", | ||
tokenFeeder: types.TokenFeeder{ | ||
TokenID: 1, | ||
// set current height to 100 to test fail case | ||
StartBaseBlock: 10, | ||
}, | ||
height: 100, | ||
err: types.ErrInvalidParams.Wrap("invalid tokenFeeder to update, invalid StartBaseBlock"), | ||
}, | ||
{ | ||
name: "invalid update, for running feeder, set EndBlock to history height", | ||
tokenFeeder: types.TokenFeeder{ | ||
TokenID: 1, | ||
// set current height to 2000000 to test fail case | ||
EndBlock: 1500000, | ||
}, | ||
height: 2000000, | ||
err: types.ErrInvalidParams.Wrap("invalid tokenFeeder to update, invalid EndBlock"), | ||
}, | ||
{ | ||
name: "invalid update, for stopped feeder, restart a feeder with wrong StartRoundID", | ||
tokenFeeder: types.TokenFeeder{ | ||
TokenID: 2, | ||
RuleID: 1, | ||
// set current height to 100 | ||
StartBaseBlock: 1000, | ||
// should be 4 | ||
StartRoundID: 5, | ||
Interval: 10, | ||
}, | ||
height: 100, | ||
err: types.ErrInvalidParams.Wrap("invalid tokenFeeder to update"), | ||
}, | ||
// success adding/updating, but fail validation | ||
{ | ||
name: "invalid update, for new feeder, EndBlock is not set properly", | ||
tokenFeeder: types.TokenFeeder{ | ||
TokenID: 3, | ||
StartBaseBlock: 10, | ||
StartRoundID: 1, | ||
Interval: 10, | ||
EndBlock: 51, | ||
}, | ||
height: 1, | ||
err: types.ErrInvalidParams.Wrap("invalid tokenFeeder, invalid EndBlock"), | ||
}, | ||
{ | ||
name: "invalid update, for new feeder, tokenID not exists", | ||
tokenFeeder: types.TokenFeeder{ | ||
TokenID: 4, | ||
StartBaseBlock: 10, | ||
StartRoundID: 1, | ||
Interval: 10, | ||
EndBlock: 58, | ||
}, | ||
height: 1, | ||
err: types.ErrInvalidParams.Wrap("invalid tokenFeeder, non-exist tokenID referred"), | ||
}, | ||
} | ||
p := types.DefaultParams() | ||
p.Tokens = append(p.Tokens, &types.Token{ | ||
Name: "TEST", | ||
ChainID: 1, | ||
ContractAddress: "0x", | ||
Decimal: 8, | ||
Active: true, | ||
AssetID: "", | ||
}) | ||
p.Tokens = append(p.Tokens, &types.Token{ | ||
Name: "TEST_NEW", | ||
ChainID: 1, | ||
ContractAddress: "0x", | ||
Decimal: 8, | ||
Active: true, | ||
AssetID: "", | ||
}) | ||
p.TokenFeeders = append(p.TokenFeeders, &types.TokenFeeder{ | ||
TokenID: 2, | ||
RuleID: 1, | ||
StartRoundID: 1, | ||
StartBaseBlock: 10, | ||
Interval: 10, | ||
EndBlock: 38, | ||
}) | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
p, err := p.UpdateTokenFeeder(&tt.tokenFeeder, tt.height) | ||
if err == nil { | ||
err = p.Validate() | ||
} | ||
if tt.err != nil { | ||
require.ErrorIs(t, err, tt.err) | ||
} | ||
}) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you add UT for update end_block for different conditions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there're cases for end_block update:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
add some new cases:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
Codebase Verification
Consider security implications of the commented-out authority check.
The authority check is still commented out in the file
x/oracle/keeper/msg_server_update_params.go
. It's crucial to ensure this is re-enabled in production to prevent unauthorized updates to parameters.x/oracle/keeper/msg_server_update_params.go
Analysis chain
Consider security implications of the commented-out authority check.
The authority check is commented out with a TODO note for testing purposes. It's crucial to ensure this is re-enabled in production to prevent unauthorized updates to parameters.
Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 471
Script:
Length of output: 129