├── .gitattributes ├── x ├── photon │ ├── types │ │ ├── types.go │ │ ├── const.go │ │ ├── events.go │ │ ├── keys.go │ │ ├── genesis.go │ │ ├── errors.go │ │ ├── genesis_test.go │ │ ├── params.go │ │ ├── codec.go │ │ ├── expected_keepers.go │ │ ├── msgs_test.go │ │ └── msgs.go │ ├── ante │ │ ├── expected_keepers.go │ │ ├── expected_keepers_mocks_test.go │ │ └── ante.go │ ├── keeper │ │ ├── params_test.go │ │ ├── params.go │ │ ├── resolver.go │ │ ├── grpc_query.go │ │ ├── grpc_query_test.go │ │ └── keeper.go │ ├── simulation │ │ ├── decoder.go │ │ ├── proposals.go │ │ └── genesis.go │ ├── genesis_test.go │ ├── genesis.go │ ├── module_simulation.go │ ├── testutil │ │ └── keeper.go │ └── client │ │ └── cli │ │ ├── tx.go │ │ └── query.go ├── coredaos │ ├── genesis_test.go │ ├── types │ │ ├── keys.go │ │ ├── events.go │ │ ├── genesis.go │ │ ├── errors.go │ │ ├── codec.go │ │ └── genesis_test.go │ ├── keeper │ │ ├── params.go │ │ ├── params_test.go │ │ ├── grpc_query_test.go │ │ ├── grpc_query.go │ │ └── keeper.go │ ├── simulation │ │ ├── decoder.go │ │ └── proposals.go │ ├── genesis.go │ ├── module_simulation.go │ ├── client │ │ └── cli │ │ │ └── query.go │ └── testutil │ │ └── keeper.go ├── gov │ └── types │ │ ├── errors.go │ │ ├── keys.go │ │ ├── v1 │ │ ├── quorum_check.go │ │ ├── exported.go │ │ ├── delegation.go │ │ ├── deposit.go │ │ ├── content.go │ │ ├── min_deposit.go │ │ ├── codec.go │ │ └── tally.go │ │ └── v1beta1 │ │ ├── deposit.go │ │ ├── content.go │ │ ├── proposals_test.go │ │ ├── router.go │ │ ├── codec.go │ │ ├── tally.go │ │ └── genesis.go └── dynamicfee │ ├── keeper │ ├── abci.go │ ├── genesis.go │ ├── msg_server.go │ ├── query_server.go │ └── genesis_test.go │ ├── post │ └── expected_keepers.go │ ├── simulation │ └── decoder.go │ ├── types │ ├── errors.go │ ├── genesis_test.go │ ├── keys.go │ ├── msgs_test.go │ ├── codec.go │ ├── genesis.go │ ├── msgs.go │ └── resolver.go │ ├── ante │ └── expected_keepers.go │ ├── module_simulation.go │ ├── fuzz │ └── tx_priority_test.go │ └── testutil │ └── keeper.go ├── .dockerignore ├── app ├── const.go ├── params │ ├── encoding.go │ ├── amino.go │ ├── doc.go │ ├── config.go │ └── weights.go ├── upgrades │ ├── v3 │ │ └── constants.go │ ├── v2 │ │ └── constants.go │ ├── v4 │ │ ├── constants.go │ │ └── upgrades.go │ └── types.go ├── genesis.go ├── genesis_account_fuzz_test.go ├── app_test.go ├── genesis_account.go └── sim_bench_test.go ├── docs ├── v2 - Zellic Audit Report.pdf ├── v3 - Zellic Audit Report.pdf └── architecture │ ├── img │ ├── adr-001-voting-period-extension-late-quorum-case1.png │ └── adr-001-voting-period-extension-late-quorum-case2.png │ ├── demo │ └── README_NakamotoBonus.md │ └── adr-template.md ├── client └── docs │ ├── embed.go │ └── swagger-ui │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── index.html ├── buf.work.yaml ├── contrib ├── localnet │ ├── proposal_text.json │ ├── proposal_upgrade.json │ └── proposal_legacy_param_change.json ├── devdeps │ └── tools.go ├── get_node.sh ├── denom.json ├── githooks │ ├── README.md │ ├── pre-commit │ └── precommit ├── Dockerfile.test ├── single-node.sh ├── scripts │ └── test_localnet_liveness.sh └── generate_release_note │ └── main.go ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ ├── md-link-checker.yml │ ├── stale.yml │ ├── lint.yml │ ├── release.yml │ ├── sim-label.yml │ ├── docker-push.yml │ ├── nightly-tests.yml │ ├── codeql-analysis.yml │ └── release-sims.yml ├── codecov.yml ├── ISSUE_TEMPLATE │ ├── issue-template.md │ ├── bug-report.md │ └── feature-request.md ├── PULL_REQUEST_TEMPLATE │ ├── others.md │ ├── docs.md │ └── production.md └── stale.yml ├── proto ├── buf.gen.swagger.yaml ├── buf.gen.gogo.yaml ├── atomone │ ├── photon │ │ └── v1 │ │ │ ├── genesis.proto │ │ │ ├── photon.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── coredaos │ │ ├── v1 │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── coredaos.proto │ │ └── module │ │ │ └── v1 │ │ │ └── module.proto │ ├── dynamicfee │ │ ├── module │ │ │ └── v1 │ │ │ │ └── module.proto │ │ └── v1 │ │ │ ├── tx.proto │ │ │ └── genesis.proto │ └── gov │ │ ├── module │ │ └── v1 │ │ │ └── module.proto │ │ └── v1beta1 │ │ └── genesis.proto ├── scripts │ ├── protocgen.sh │ └── protoc-swagger-gen.sh ├── buf.yaml └── buf.lock ├── tests └── e2e │ ├── docker │ └── hermes.Dockerfile │ ├── keys.go │ ├── doc.go │ ├── e2e_slashing_test.go │ ├── address.go │ ├── io.go │ ├── e2e_encode_test.go │ ├── e2e_evidence_test.go │ └── chain_test.go ├── mlc_config.json ├── cmd └── atomoned │ ├── main.go │ └── cmd │ ├── config.go │ ├── root_test.go │ ├── tx.go │ └── bech32_convert.go ├── Dockerfile ├── .mergify.yml ├── pkg └── address │ ├── address.go │ └── address_test.go ├── e2e.Dockerfile ├── .gitignore ├── post └── post.go ├── .build.sh ├── types └── errors │ └── errors.go ├── .goreleaser.yml ├── README.md └── .golangci.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /x/photon/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | -------------------------------------------------------------------------------- /x/coredaos/genesis_test.go: -------------------------------------------------------------------------------- 1 | package coredaos_test 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .github 4 | .vscode -------------------------------------------------------------------------------- /app/const.go: -------------------------------------------------------------------------------- 1 | package atomone 2 | 3 | const ( 4 | appName = "AtomOneApp" 5 | ) 6 | -------------------------------------------------------------------------------- /docs/v2 - Zellic Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomone-hub/atomone/HEAD/docs/v2 - Zellic Audit Report.pdf -------------------------------------------------------------------------------- /docs/v3 - Zellic Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomone-hub/atomone/HEAD/docs/v3 - Zellic Audit Report.pdf -------------------------------------------------------------------------------- /client/docs/embed.go: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import ( 4 | "embed" 5 | ) 6 | 7 | //go:embed swagger-ui/* 8 | var SwaggerUI embed.FS 9 | -------------------------------------------------------------------------------- /client/docs/swagger-ui/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomone-hub/atomone/HEAD/client/docs/swagger-ui/favicon-16x16.png -------------------------------------------------------------------------------- /client/docs/swagger-ui/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomone-hub/atomone/HEAD/client/docs/swagger-ui/favicon-32x32.png -------------------------------------------------------------------------------- /buf.work.yaml: -------------------------------------------------------------------------------- 1 | # This workspace file points to the roots found in your 2 | # previous "buf.yaml" configuration. 3 | version: v1 4 | directories: 5 | - proto 6 | -------------------------------------------------------------------------------- /contrib/localnet/proposal_text.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": "ipfs://CID", 3 | "deposit": "512000000uatone", 4 | "title": "text proposal", 5 | "summary": "my summary" 6 | } 7 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # CODEOWNERS: https://help.github.com/articles/about-codeowners/ 2 | 3 | # Primary repo maintainers 4 | * @giunatale @tbruyelle @jaekwon @giuliostramondo 5 | 6 | -------------------------------------------------------------------------------- /docs/architecture/img/adr-001-voting-period-extension-late-quorum-case1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomone-hub/atomone/HEAD/docs/architecture/img/adr-001-voting-period-extension-late-quorum-case1.png -------------------------------------------------------------------------------- /docs/architecture/img/adr-001-voting-period-extension-late-quorum-case2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomone-hub/atomone/HEAD/docs/architecture/img/adr-001-voting-period-extension-late-quorum-case2.png -------------------------------------------------------------------------------- /x/photon/types/const.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | 5 | // Denom name 6 | Denom = "uphoton" 7 | 8 | // Photon max supply is 1B 9 | MaxSupply int64 = 1_000_000_000 * 1_000_000 10 | ) 11 | -------------------------------------------------------------------------------- /proto/buf.gen.swagger.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: swagger 4 | out: ./tmp-swagger-gen 5 | opt: 6 | - logtostderr=true 7 | - fqn_for_swagger_name=true 8 | - simple_operation_ids=true 9 | -------------------------------------------------------------------------------- /x/photon/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Photon module event types 4 | const ( 5 | EventTypeMintPhoton = "mint_photon" 6 | 7 | AttributeKeyBurned = "burned" 8 | AttributeKeyMinted = "minted" 9 | ) 10 | -------------------------------------------------------------------------------- /x/gov/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "cosmossdk.io/errors" 5 | ) 6 | 7 | // x/gov module sentinel errors 8 | var ( 9 | ErrUnknownProposal = errors.Register(ModuleName, 180, "unknown proposal") 10 | ) 11 | -------------------------------------------------------------------------------- /x/gov/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "gov" 6 | 7 | // StoreKey is the store key string for gov 8 | StoreKey = ModuleName 9 | 10 | RouterKey = ModuleName 11 | ) 12 | -------------------------------------------------------------------------------- /tests/e2e/docker/hermes.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=linux/amd64 informalsystems/hermes:1.10.0 AS hermes-builder 2 | 3 | FROM --platform=linux/amd64 debian:buster-slim 4 | USER root 5 | 6 | COPY --from=hermes-builder /usr/bin/hermes /usr/local/bin/ 7 | RUN chmod +x /usr/local/bin/hermes 8 | 9 | EXPOSE 3031 -------------------------------------------------------------------------------- /mlc_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignorePatterns": [ { "pattern": "^https://ipfs.io/ipfs/" } ], 3 | "replacementPatterns": [ ], 4 | "httpHeaders": [ ], 5 | "timeout": "20s", 6 | "retryOn429": true, 7 | "retryCount": 5, 8 | "fallbackRetryDelay": "30s", 9 | "aliveStatusCodes": [0, 200, 206, 403, 429] 10 | } 11 | -------------------------------------------------------------------------------- /x/photon/ante/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | photontypes "github.com/atomone-hub/atomone/x/photon/types" 7 | ) 8 | 9 | // PhotonKeeper defines the expected photon keeper. 10 | type PhotonKeeper interface { 11 | GetParams(ctx sdk.Context) photontypes.Params 12 | } 13 | -------------------------------------------------------------------------------- /proto/buf.gen.gogo.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: gocosmos 4 | out: .. 5 | opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/app/v1alpha1/module.proto=cosmossdk.io/api/cosmos/app/v1alpha1 6 | - name: grpc-gateway 7 | out: .. 8 | opt: logtostderr=true,allow_colon_final_segments=true 9 | -------------------------------------------------------------------------------- /x/photon/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName defines the module name 5 | ModuleName = "photon" 6 | 7 | // StoreKey defines the primary module store key 8 | StoreKey = ModuleName 9 | 10 | // RouterKey defines the module's message routing key 11 | RouterKey = ModuleName 12 | ) 13 | 14 | var ParamsKey = []byte{0x00} 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please go the the `Preview` tab and select the appropriate sub-template: 2 | 3 | * [Production code](?expand=1&template=production.md) - for types `fix`, `feat`, and `refactor`. 4 | * [Docs](?expand=1&template=docs.md) - for documentation changes. 5 | * [Others](?expand=1&template=others.md) - for changes that do not affect production code. -------------------------------------------------------------------------------- /x/gov/types/v1/quorum_check.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | time "time" 5 | ) 6 | 7 | func NewQuorumCheckQueueEntry(quorumTimeoutTime time.Time, quorumCheckCount uint64) QuorumCheckQueueEntry { 8 | return QuorumCheckQueueEntry{ 9 | QuorumTimeoutTime: &quorumTimeoutTime, 10 | QuorumCheckCount: quorumCheckCount, 11 | QuorumChecksDone: 0, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/md-link-checker.yml: -------------------------------------------------------------------------------- 1 | name: Check Markdown links 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '* */24 * * *' 6 | jobs: 7 | markdown-link-check: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: gaurav-nelson/github-action-markdown-link-check@1.0.15 12 | with: 13 | folder-path: "docs" -------------------------------------------------------------------------------- /contrib/devdeps/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package devdeps 4 | 5 | import ( 6 | // formatting 7 | _ "mvdan.cc/gofumpt" 8 | 9 | // linter 10 | _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 11 | 12 | // mocks 13 | _ "github.com/golang/mock/mockgen" 14 | 15 | // for releases 16 | _ "github.com/goreleaser/goreleaser" 17 | 18 | _ "golang.org/x/vuln/cmd/govulncheck" 19 | ) 20 | -------------------------------------------------------------------------------- /x/coredaos/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "cosmossdk.io/collections" 4 | 5 | const ( 6 | // ModuleName defines the module name 7 | ModuleName = "coredaos" 8 | 9 | // StoreKey defines the primary module store key 10 | StoreKey = ModuleName 11 | 12 | // RouterKey defines the module's message routing key 13 | RouterKey = ModuleName 14 | ) 15 | 16 | var ParamsKey = collections.NewPrefix(0) 17 | -------------------------------------------------------------------------------- /tests/e2e/keys.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "github.com/cosmos/go-bip39" 5 | ) 6 | 7 | // createMnemonic creates a random string mnemonic 8 | func createMnemonic() (string, error) { 9 | entropySeed, err := bip39.NewEntropy(256) 10 | if err != nil { 11 | return "", err 12 | } 13 | 14 | mnemonic, err := bip39.NewMnemonic(entropySeed) 15 | if err != nil { 16 | return "", err 17 | } 18 | 19 | return mnemonic, nil 20 | } 21 | -------------------------------------------------------------------------------- /cmd/atomoned/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 8 | 9 | app "github.com/atomone-hub/atomone/app" 10 | "github.com/atomone-hub/atomone/cmd/atomoned/cmd" 11 | ) 12 | 13 | func main() { 14 | rootCmd, _ := cmd.NewRootCmd() 15 | 16 | if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { 17 | fmt.Fprintln(rootCmd.OutOrStderr(), err) 18 | os.Exit(1) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /proto/atomone/photon/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.photon.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "atomone/photon/v1/photon.proto"; 6 | import "amino/amino.proto"; 7 | 8 | option go_package = "github.com/atomone-hub/atomone/x/photon/types"; 9 | 10 | // GenesisState defines the x/photon module's genesis state. 11 | message GenesisState { 12 | Params params = 1 [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 13 | } 14 | -------------------------------------------------------------------------------- /proto/atomone/coredaos/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.coredaos.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "atomone/coredaos/v1/coredaos.proto"; 6 | import "amino/amino.proto"; 7 | 8 | option go_package = "github.com/atomone-hub/atomone/x/coredaos/types"; 9 | 10 | // GenesisState defines the x/coredaos module's genesis state. 11 | message GenesisState { 12 | Params params = 1 [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 13 | } 14 | -------------------------------------------------------------------------------- /x/coredaos/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "cosmossdk.io/collections" 8 | 9 | "github.com/atomone-hub/atomone/x/coredaos/types" 10 | ) 11 | 12 | // GetParams get all parameters as types.Params 13 | func (k Keeper) GetParams(ctx context.Context) (params types.Params) { 14 | params, err := k.Params.Get(ctx) 15 | if err != nil && !errors.Is(err, collections.ErrNotFound) { 16 | panic(err) 17 | } 18 | return params 19 | } 20 | -------------------------------------------------------------------------------- /x/dynamicfee/keeper/abci.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // EndBlock returns an endblocker for the x/feemarket module. The endblocker 10 | // is responsible for updating the state of the fee market based on the 11 | // AIMD learning rate adjustment algorithm. 12 | func (k *Keeper) EndBlock(ctx context.Context) error { 13 | sdkCtx := sdk.UnwrapSDKContext(ctx) 14 | return k.UpdateDynamicfee(sdkCtx) 15 | } 16 | -------------------------------------------------------------------------------- /x/photon/keeper/params_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/atomone-hub/atomone/x/photon/testutil" 7 | "github.com/atomone-hub/atomone/x/photon/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestGetParams(t *testing.T) { 12 | k, _, ctx := testutil.SetupPhotonKeeper(t) 13 | params := types.DefaultParams() 14 | 15 | k.SetParams(ctx, params) 16 | got := k.GetParams(ctx) 17 | 18 | require.EqualValues(t, params, got) 19 | } 20 | -------------------------------------------------------------------------------- /contrib/localnet/proposal_upgrade.json: -------------------------------------------------------------------------------- 1 | { 2 | "messages": [ 3 | { 4 | "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", 5 | "authority": "atone10d07y265gmmuvt4z0w9aw880jnsr700j5z0zqt", 6 | "plan": { 7 | "name": "v3", 8 | "time": "0001-01-01T00:00:00Z", 9 | "height": "80", 10 | "info": "", 11 | "upgraded_client_state": null 12 | } 13 | } 14 | ], 15 | "metadata": "ipfs://CID", 16 | "deposit": "512000000uatone", 17 | "title": "v3", 18 | "summary": "v3" 19 | } 20 | -------------------------------------------------------------------------------- /x/dynamicfee/post/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package post 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 7 | ) 8 | 9 | type DynamicfeeKeeper interface { 10 | GetState(ctx context.Context) (types.State, error) 11 | GetParams(ctx context.Context) (types.Params, error) 12 | GetMaxBlockGas(ctx context.Context, params types.Params) uint64 13 | SetState(ctx context.Context, state types.State) error 14 | GetEnabledHeight(ctx context.Context) (int64, error) 15 | } 16 | -------------------------------------------------------------------------------- /x/coredaos/keeper/params_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/atomone-hub/atomone/x/coredaos/testutil" 7 | "github.com/atomone-hub/atomone/x/coredaos/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestGetParams(t *testing.T) { 12 | k, _, ctx := testutil.SetupCoredaosKeeper(t) 13 | params := types.DefaultParams() 14 | 15 | k.Params.Set(ctx, params) 16 | got := k.GetParams(ctx) 17 | 18 | require.EqualValues(t, params, got) 19 | } 20 | -------------------------------------------------------------------------------- /x/photon/simulation/decoder.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/types/kv" 8 | ) 9 | 10 | // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's 11 | // Value to the corresponding photon type. 12 | func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { 13 | return func(kvA, kvB kv.Pair) string { 14 | panic(fmt.Sprintf("invalid photon key prefix %X", kvA.Key[:1])) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /x/coredaos/simulation/decoder.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/types/kv" 8 | ) 9 | 10 | // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's 11 | // Value to the corresponding coredaos type. 12 | func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { 13 | return func(kvA, kvB kv.Pair) string { 14 | panic(fmt.Sprintf("invalid coredaos key prefix %X", kvA.Key[:1])) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /x/dynamicfee/simulation/decoder.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/types/kv" 8 | ) 9 | 10 | // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's 11 | // Value to the corresponding dynamicfee type. 12 | func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { 13 | return func(kvA, kvB kv.Pair) string { 14 | panic(fmt.Sprintf("invalid dynamicfee key prefix %X", kvA.Key[:1])) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cmd/atomoned/cmd/config.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | appparams "github.com/atomone-hub/atomone/app/params" 7 | ) 8 | 9 | func init() { 10 | cfg := sdk.GetConfig() 11 | cfg.SetBech32PrefixForAccount(appparams.Bech32PrefixAccAddr, appparams.Bech32PrefixAccPub) 12 | cfg.SetBech32PrefixForValidator(appparams.Bech32PrefixValAddr, appparams.Bech32PrefixValPub) 13 | cfg.SetBech32PrefixForConsensusNode(appparams.Bech32PrefixConsAddr, appparams.Bech32PrefixConsPub) 14 | cfg.Seal() 15 | } 16 | -------------------------------------------------------------------------------- /app/params/encoding.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client" 5 | "github.com/cosmos/cosmos-sdk/codec" 6 | "github.com/cosmos/cosmos-sdk/codec/types" 7 | ) 8 | 9 | // EncodingConfig specifies the concrete encoding types to use for a given app. 10 | // This is provided for compatibility between protobuf and amino implementations. 11 | type EncodingConfig struct { 12 | InterfaceRegistry types.InterfaceRegistry 13 | Codec codec.Codec 14 | TxConfig client.TxConfig 15 | Amino *codec.LegacyAmino 16 | } 17 | -------------------------------------------------------------------------------- /proto/atomone/photon/v1/photon.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.photon.v1; 3 | 4 | option go_package = "github.com/atomone-hub/atomone/x/photon/types"; 5 | 6 | // Params defines the parameters for the x/photon module. 7 | message Params { 8 | // Allow to mint photon or not 9 | bool mint_disabled = 1; 10 | // tx_fee_exceptions holds the msg type urls that are allowed to use some 11 | // different tx fee coins than photon. 12 | // A wildcard "*" can be used to allow all transactions to use any fee denom. 13 | repeated string tx_fee_exceptions = 2; 14 | } 15 | -------------------------------------------------------------------------------- /x/coredaos/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Event types for the coredaos module 4 | const ( 5 | EventTypeAnnotateProposal = "annotate_proposal" 6 | EventTypeEndorseProposal = "endorse_proposal" 7 | EventTypeExtendVotingPeriod = "extend_voting_period" 8 | EventTypeVetoProposal = "veto_proposal" 9 | 10 | AttributeKeyProposalID = "proposal_id" 11 | AttributeKeySigner = "signer" 12 | AttributeKeyNewEndTime = "new_end_time" 13 | AttributeKeyTimesExtended = "times_extended" 14 | 15 | AttributeValueProposalVetoed = "proposal_vetoed" 16 | ) 17 | -------------------------------------------------------------------------------- /app/upgrades/v3/constants.go: -------------------------------------------------------------------------------- 1 | package v3 2 | 3 | import ( 4 | storetypes "cosmossdk.io/store/types" 5 | 6 | "github.com/atomone-hub/atomone/app/upgrades" 7 | dynamicfeetypes "github.com/atomone-hub/atomone/x/dynamicfee/types" 8 | ) 9 | 10 | const ( 11 | UpgradeName = "v3" 12 | ) 13 | 14 | var Upgrade = upgrades.Upgrade{ 15 | UpgradeName: UpgradeName, 16 | CreateUpgradeHandler: CreateUpgradeHandler, 17 | StoreUpgrades: storetypes.StoreUpgrades{ 18 | Added: []string{ 19 | // new module added in v3 20 | dynamicfeetypes.ModuleName, 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /contrib/get_node.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VERSION=v11.15.0 4 | NODE_FULL=node-${VERSION}-linux-x64 5 | 6 | mkdir -p ~/.local/bin 7 | mkdir -p ~/.local/node 8 | wget http://nodejs.org/dist/${VERSION}/${NODE_FULL}.tar.gz -O ~/.local/node/${NODE_FULL}.tar.gz 9 | tar -xzf ~/.local/node/${NODE_FULL}.tar.gz -C ~/.local/node/ 10 | ln -s ~/.local/node/${NODE_FULL}/bin/node ~/.local/bin/node 11 | ln -s ~/.local/node/${NODE_FULL}/bin/npm ~/.local/bin/npm 12 | export PATH=~/.local/bin:$PATH 13 | npm i -g dredd@11.0.1 14 | ln -s ~/.local/node/${NODE_FULL}/bin/dredd ~/.local/bin/dredd 15 | -------------------------------------------------------------------------------- /x/dynamicfee/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdkerrors "cosmossdk.io/errors" 5 | ) 6 | 7 | var ( 8 | ErrNoFeeCoins = sdkerrors.New(ModuleName, 1, "no fee coin provided. Must provide one.") 9 | ErrTooManyFeeCoins = sdkerrors.New(ModuleName, 2, "too many fee coins provided. Only one fee coin may be provided") 10 | ErrResolverNotSet = sdkerrors.New(ModuleName, 3, "denom resolver interface not set. Only the dynamicfee base fee denomination can be used") 11 | ErrMaxGasExceeded = sdkerrors.New(ModuleName, 4, "block gas cannot exceed max block gas") 12 | ) 13 | -------------------------------------------------------------------------------- /x/photon/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // NewGenesisState creates a new genesis state for the governance module 4 | func NewGenesisState(params Params) *GenesisState { 5 | return &GenesisState{ 6 | Params: params, 7 | } 8 | } 9 | 10 | // DefaultGenesis returns the default genesis state 11 | func DefaultGenesis() *GenesisState { 12 | return NewGenesisState(DefaultParams()) 13 | } 14 | 15 | // Validate performs basic genesis state validation returning an error upon any 16 | // failure. 17 | func (gs GenesisState) Validate() error { 18 | return gs.Params.ValidateBasic() 19 | } 20 | -------------------------------------------------------------------------------- /app/genesis.go: -------------------------------------------------------------------------------- 1 | package atomone 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // The genesis state of the blockchain is represented here as a map of raw json 8 | // messages key'd by a identifier string. 9 | // The identifier is used to determine which module genesis information belongs 10 | // to so it may be appropriately routed during init chain. 11 | // Within this application default genesis information is retrieved from 12 | // the ModuleBasicManager which populates json from each BasicModule 13 | // object provided to it during init. 14 | type GenesisState map[string]json.RawMessage 15 | -------------------------------------------------------------------------------- /proto/scripts/protocgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | echo "Generating gogo proto code" 5 | cd proto 6 | proto_dirs=$(find ./ -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 7 | for dir in $proto_dirs; do 8 | for file in $(find "${dir}" -maxdepth 1 -name '*.proto'); do 9 | if grep "option go_package" $file &> /dev/null ; then 10 | buf generate --template buf.gen.gogo.yaml $file 11 | fi 12 | done 13 | done 14 | cd .. 15 | # move proto files to the right places 16 | cp -r github.com/atomone-hub/atomone/* ./ 17 | rm -rf github.com 18 | -------------------------------------------------------------------------------- /x/coredaos/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // NewGenesisState creates a new genesis state for the governance module 4 | func NewGenesisState(params Params) *GenesisState { 5 | return &GenesisState{ 6 | Params: params, 7 | } 8 | } 9 | 10 | // DefaultGenesis returns the default genesis state 11 | func DefaultGenesis() *GenesisState { 12 | return NewGenesisState(DefaultParams()) 13 | } 14 | 15 | // Validate performs basic genesis state validation returning an error upon any 16 | // failure. 17 | func (gs GenesisState) Validate() error { 18 | return gs.Params.ValidateBasic() 19 | } 20 | -------------------------------------------------------------------------------- /proto/atomone/coredaos/module/v1/module.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package atomone.coredaos.module.v1; 4 | 5 | import "cosmos/app/v1alpha1/module.proto"; 6 | 7 | option go_package = "github.com/atomone-hub/atomone/x/coredaos/types/module"; 8 | 9 | // Module is the config object of the builder module. 10 | message Module { 11 | option (cosmos.app.v1alpha1.module) = { 12 | go_import : "github.com/atomone-hub/atomone/x/coredaos" 13 | }; 14 | 15 | // Authority defines the custom module authority. If not set, defaults to the 16 | // governance module. 17 | string authority = 1; 18 | } 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMG_TAG=latest 2 | 3 | # Compile the atomoned binary 4 | FROM golang:1.22-alpine AS atomoned-builder 5 | WORKDIR /src/app/ 6 | COPY go.mod go.sum* ./ 7 | RUN go mod download 8 | COPY . . 9 | ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 10 | RUN apk add --no-cache $PACKAGES 11 | RUN CGO_ENABLED=0 make install 12 | 13 | # Add to a distroless container 14 | FROM cgr.dev/chainguard/static:$IMG_TAG 15 | ARG IMG_TAG 16 | COPY --from=atomoned-builder /go/bin/atomoned /usr/local/bin/ 17 | EXPOSE 26656 26657 1317 9090 18 | USER 0 19 | 20 | ENTRYPOINT ["atomoned", "start"] 21 | -------------------------------------------------------------------------------- /app/upgrades/v2/constants.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | store "cosmossdk.io/store/types" 5 | 6 | "github.com/atomone-hub/atomone/app/upgrades" 7 | photontypes "github.com/atomone-hub/atomone/x/photon/types" 8 | ) 9 | 10 | const ( 11 | UpgradeName = "v2" 12 | ) 13 | 14 | var Upgrade = upgrades.Upgrade{ 15 | UpgradeName: UpgradeName, 16 | CreateUpgradeHandler: CreateUpgradeHandler, 17 | StoreUpgrades: store.StoreUpgrades{ 18 | Added: []string{ 19 | // new module added in v2 20 | photontypes.ModuleName, 21 | }, 22 | Deleted: []string{ 23 | "crisis", 24 | }, 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /contrib/denom.json: -------------------------------------------------------------------------------- 1 | 2 | 3 | [{ 4 | "base": "uatone", 5 | "denom_units": [ 6 | { 7 | "aliases": [ 8 | "microatone" 9 | ], 10 | "denom": "uatone", 11 | "exponent": 0 12 | }, 13 | { 14 | "aliases": [ 15 | "milliatone" 16 | ], 17 | "denom": "matone", 18 | "exponent": 3 19 | }, 20 | { 21 | "aliases": [], 22 | "denom": "atone", 23 | "exponent": 6 24 | } 25 | ], 26 | "description": "The native staking token of AtomOne.", 27 | "display": "ATONE", 28 | "name": "ATONE", 29 | "symbol": "ATONE" 30 | }] 31 | -------------------------------------------------------------------------------- /proto/atomone/dynamicfee/module/v1/module.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package atomone.dynamicfee.module.v1; 4 | 5 | import "cosmos/app/v1alpha1/module.proto"; 6 | 7 | option go_package = "github.com/atomone-hub/atomone/x/dynamicfee/types/module"; 8 | 9 | // Module is the config object of the builder module. 10 | message Module { 11 | option (cosmos.app.v1alpha1.module) = { 12 | go_import : "github.com/atomone-hub/atomone/x/dynamicfee" 13 | }; 14 | 15 | // Authority defines the custom module authority. If not set, defaults to the 16 | // governance module. 17 | string authority = 1; 18 | } 19 | -------------------------------------------------------------------------------- /x/dynamicfee/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 9 | ) 10 | 11 | func TestGenesis(t *testing.T) { 12 | t.Run("can create a new default genesis state", func(t *testing.T) { 13 | gs := types.DefaultGenesisState() 14 | require.NoError(t, gs.ValidateBasic()) 15 | }) 16 | 17 | t.Run("can accept a valid genesis state for AIMD eip-1559", func(t *testing.T) { 18 | gs := types.DefaultAIMDGenesisState() 19 | require.NoError(t, gs.ValidateBasic()) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | defaults: 2 | actions: 3 | backport: 4 | assignees: 5 | - "{{ author }}" 6 | 7 | queue_rules: 8 | - name: default 9 | conditions: 10 | - "#approved-reviews-by>1" 11 | 12 | pull_request_rules: 13 | - name: Automatic merge on approval to the main branch 14 | conditions: 15 | - "#approved-reviews-by>=1" 16 | - base=main 17 | - label=A:automerge 18 | actions: 19 | queue: 20 | name: default 21 | merge: 22 | method: squash 23 | commit_message_template: | 24 | {{ title }} (#{{ number }}) 25 | {{ body }} 26 | -------------------------------------------------------------------------------- /cmd/atomoned/cmd/root_test.go: -------------------------------------------------------------------------------- 1 | package cmd_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 9 | 10 | app "github.com/atomone-hub/atomone/app" 11 | "github.com/atomone-hub/atomone/cmd/atomoned/cmd" 12 | ) 13 | 14 | func TestRootCmdConfig(t *testing.T) { 15 | rootCmd, _ := cmd.NewRootCmd() 16 | rootCmd.SetArgs([]string{ 17 | "config", // Test the config cmd 18 | "keyring-backend", // key 19 | "test", // value 20 | }) 21 | 22 | require.NoError(t, svrcmd.Execute(rootCmd, "", app.DefaultNodeHome)) 23 | } 24 | -------------------------------------------------------------------------------- /contrib/githooks/README.md: -------------------------------------------------------------------------------- 1 | # Git hooks 2 | 3 | Installation: 4 | 5 | ``` 6 | git config core.hooksPath contrib/githooks 7 | ``` 8 | 9 | ## pre-commit 10 | 11 | The hook automatically runs `gofmt`, `goimports`, and `misspell` 12 | to correctly format the `.go` files included in the commit, provided 13 | that all the aforementioned commands are installed and available 14 | in the user's search `$PATH` environment variable: 15 | 16 | ``` 17 | go install golang.org/x/tools/cmd/goimports 18 | go install github.com/golangci/misspell/cmd/misspell@master 19 | ``` 20 | 21 | It also runs `go mod tidy` and `golangci-lint` if available. 22 | -------------------------------------------------------------------------------- /x/gov/types/v1/exported.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | sdkgovtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 5 | ) 6 | 7 | type GovernorI interface { 8 | GetMoniker() string // moniker of the governor 9 | GetStatus() GovernorStatus // status of the governor 10 | IsActive() bool // check if has a active status 11 | IsInactive() bool // check if has status inactive 12 | GetAddress() sdkgovtypes.GovernorAddress // governor address to receive/return governors delegations 13 | GetDescription() GovernorDescription // description of the governor 14 | } 15 | -------------------------------------------------------------------------------- /tests/e2e/doc.go: -------------------------------------------------------------------------------- 1 | // package e2e defines an integration testing suite used for full end-to-end 2 | // testing functionality. 3 | // 4 | // The file e2e_suite_test.go defines the testing suite and contains the core 5 | // bootrapping logic that creates a testing environment via Docker containers. 6 | // A testing network is created dynamically and contains multiple Docker 7 | // containers: 8 | // 9 | // 1. Two independent AtomOne networks 10 | // 3. A hermes relayer connecting the two AtomOne networks over IBC 11 | // 12 | // The file e2e_test.go contains the actual end-to-end integration tests that 13 | // utilize the testing suite. 14 | package e2e 15 | -------------------------------------------------------------------------------- /x/photon/genesis_test.go: -------------------------------------------------------------------------------- 1 | package photon_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/atomone-hub/atomone/x/photon" 9 | "github.com/atomone-hub/atomone/x/photon/testutil" 10 | "github.com/atomone-hub/atomone/x/photon/types" 11 | ) 12 | 13 | func TestGenesis(t *testing.T) { 14 | genesisState := types.GenesisState{ 15 | Params: types.DefaultParams(), 16 | } 17 | k, _, ctx := testutil.SetupPhotonKeeper(t) 18 | 19 | photon.InitGenesis(ctx, *k, genesisState) 20 | got := photon.ExportGenesis(ctx, *k) 21 | 22 | require.NotNil(t, got) 23 | require.Equal(t, genesisState, *got) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/address/address.go: -------------------------------------------------------------------------------- 1 | package address 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/types/bech32" 7 | ) 8 | 9 | // ConvertBech32Prefix convert bech32 address to specified prefix. 10 | func ConvertBech32Prefix(address, prefix string) (string, error) { 11 | _, bz, err := bech32.DecodeAndConvert(address) 12 | if err != nil { 13 | return "", fmt.Errorf("cannot decode %s address: %s", address, err) 14 | } 15 | 16 | convertedAddress, err := bech32.ConvertAndEncode(prefix, bz) 17 | if err != nil { 18 | return "", fmt.Errorf("cannot convert %s address: %s", address, err) 19 | } 20 | 21 | return convertedAddress, nil 22 | } 23 | -------------------------------------------------------------------------------- /tests/e2e/e2e_slashing_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | const jailedValidatorKey = "jailed" 4 | 5 | func (s *IntegrationTestSuite) testSlashing(chainEndpoint string) { 6 | s.Run("unjail validator", func() { 7 | validators, err := s.queryValidators(chainEndpoint) 8 | s.Require().NoError(err) 9 | 10 | for _, val := range validators { 11 | if val.Jailed { 12 | s.execUnjail( 13 | s.chainA, 14 | withKeyValue(flagFrom, jailedValidatorKey), 15 | ) 16 | 17 | valQ, err := s.queryValidator(chainEndpoint, val.OperatorAddress) 18 | s.Require().NoError(err) 19 | s.Require().False(valQ.Jailed) 20 | } 21 | } 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /e2e.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION 2 | ARG IMG_TAG=latest 3 | 4 | # Compile the atomoned binary 5 | FROM golang:$GO_VERSION-alpine AS atomoned-builder 6 | WORKDIR /src/app/ 7 | COPY go.mod go.sum* ./ 8 | RUN go mod download 9 | COPY . . 10 | ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 11 | RUN apk add --no-cache $PACKAGES 12 | RUN CGO_ENABLED=0 make install 13 | 14 | # Add to a distroless container 15 | FROM alpine:$IMG_TAG 16 | RUN adduser -D nonroot 17 | ARG IMG_TAG 18 | COPY --from=atomoned-builder /go/bin/atomoned /usr/local/bin/ 19 | EXPOSE 26656 26657 1317 9090 20 | USER nonroot 21 | 22 | ENTRYPOINT ["atomoned", "start"] 23 | -------------------------------------------------------------------------------- /x/photon/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | // x/photon module sentinel errors 8 | var ( 9 | ErrMintDisabled = errorsmod.Register(ModuleName, 1, "photon mint disabled") 10 | ErrBurnInvalidDenom = errorsmod.Register(ModuleName, 2, "invalid burned amount denom: expected bond denom") 11 | ErrZeroMintPhotons = errorsmod.Register(ModuleName, 3, "no mintable photon after rounding, try higher burn") 12 | ErrTooManyFeeCoins = errorsmod.Register(ModuleName, 5, "too many fee coins, only accepts fees in one denom") 13 | ErrInvalidFeeToken = errorsmod.Register(ModuleName, 6, "invalid fee token") 14 | ) 15 | -------------------------------------------------------------------------------- /x/coredaos/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | // x/photon module sentinel errors 8 | var ( 9 | ErrInvalidSigner = errorsmod.Register(ModuleName, 1, "expected core DAO account as only signer for this message") 10 | ErrAnnotationAlreadyPresent = errorsmod.Register(ModuleName, 2, "annotation already present") 11 | ErrProposalAlreadyEndorsed = errorsmod.Register(ModuleName, 3, "proposal already endorsed") 12 | ErrFunctionDisabled = errorsmod.Register(ModuleName, 4, "function is disabled") 13 | ErrCannotStake = errorsmod.Register(ModuleName, 5, "core DAOs cannot stake") 14 | ) 15 | -------------------------------------------------------------------------------- /x/coredaos/keeper/grpc_query_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/atomone-hub/atomone/x/coredaos/keeper" 7 | "github.com/atomone-hub/atomone/x/coredaos/testutil" 8 | "github.com/atomone-hub/atomone/x/coredaos/types" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestParamsQuery(t *testing.T) { 13 | k, _, ctx := testutil.SetupCoredaosKeeper(t) 14 | params := types.DefaultParams() 15 | k.Params.Set(ctx, params) 16 | q := keeper.NewQuerier(*k) 17 | resp, err := q.Params(ctx, &types.QueryParamsRequest{}) 18 | 19 | require.NoError(t, err) 20 | require.Equal(t, &types.QueryParamsResponse{Params: params}, resp) 21 | } 22 | -------------------------------------------------------------------------------- /app/params/amino.go: -------------------------------------------------------------------------------- 1 | //go:build test_amino 2 | // +build test_amino 3 | 4 | package params 5 | 6 | import ( 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 9 | "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" 10 | ) 11 | 12 | func MakeTestEncodingConfig() EncodingConfig { 13 | cdc := codec.NewLegacyAmino() 14 | interfaceRegistry := cdctypes.NewInterfaceRegistry() 15 | codec := codec.NewProtoCodec(interfaceRegistry) 16 | 17 | return EncodingConfig{ 18 | InterfaceRegistry: interfaceRegistry, 19 | Marshaler: codec, 20 | TxConfig: legacytx.StdTxConfig{Cdc: cdc}, 21 | Amino: cdc, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/params/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package params defines the simulation parameters in the atomone. 3 | 4 | It contains the default weights used for each transaction used on the module's 5 | simulation. These weights define the chance for a transaction to be simulated at 6 | any given operation. 7 | 8 | You can replace the default values for the weights by providing a params.json 9 | file with the weights defined for each of the transaction operations: 10 | 11 | { 12 | "op_weight_msg_send": 60, 13 | "op_weight_msg_delegate": 100, 14 | } 15 | 16 | In the example above, the `MsgSend` has 60% chance to be simulated, while the 17 | `MsgDelegate` will always be simulated. 18 | */ 19 | package params 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | *.swl 6 | *.swm 7 | *.swn 8 | .vscode 9 | .idea 10 | 11 | # Build 12 | artifacts 13 | vendor 14 | build 15 | tools/bin/* 16 | examples/build/* 17 | docs/_build 18 | docs/node_modules 19 | docs/tutorial 20 | dist 21 | tools-stamp 22 | docs/node_modules 23 | 24 | # Data - ideally these don't exist 25 | baseapp/data/* 26 | client/lcd/keys/* 27 | mytestnet 28 | 29 | # Testing 30 | coverage.txt 31 | profile.out 32 | 33 | # Vagrant 34 | .vagrant/ 35 | *.box 36 | *.log 37 | vagrant 38 | 39 | # IDE 40 | .idea/ 41 | *.iml 42 | 43 | # Graphviz 44 | dependency-graph.png 45 | 46 | # Latex 47 | *.aux 48 | *.out 49 | *.synctex.gz 50 | contract_tests/* 51 | 52 | go.work.sum 53 | 54 | -------------------------------------------------------------------------------- /x/dynamicfee/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the dynamicfee module. 5 | ModuleName = "dynamicfee" 6 | // StoreKey is the store key string for the dynamicfee module. 7 | StoreKey = ModuleName 8 | ) 9 | 10 | const ( 11 | prefixParams = iota + 1 12 | prefixState 13 | prefixEnableHeight = 3 14 | ) 15 | 16 | var ( 17 | // KeyParams is the store key for the dynamicfee module's parameters. 18 | KeyParams = []byte{prefixParams} 19 | 20 | // KeyState is the store key for the dynamicfee module's data. 21 | KeyState = []byte{prefixState} 22 | 23 | // KeyEnabledHeight is the store key for the dynamicfee module's enabled height. 24 | KeyEnabledHeight = []byte{prefixEnableHeight} 25 | ) 26 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale pull requests" 2 | on: 3 | schedule: 4 | - cron: "0 0 * * 1-5" 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v9.0.0 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | stale-pr-message: "This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." 14 | days-before-stale: -1 15 | days-before-close: -1 16 | days-before-pr-stale: 45 17 | days-before-pr-close: 6 18 | exempt-pr-labels: "pinned, security, proposal, blocked, ADR" 19 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | precision: 2 3 | round: down 4 | range: 70...100 5 | status: 6 | project: 7 | default: 8 | threshold: 1% # allow this much decrease on project 9 | app: 10 | target: 80% 11 | paths: # this must be a list type 12 | - "app/" 13 | changes: false 14 | 15 | comment: 16 | layout: "reach, diff, files" 17 | behavior: default # update if exists else create new 18 | require_changes: true 19 | 20 | ignore: 21 | - "*.pb.go" 22 | - "*.pb.gw.go" 23 | - "*.md" 24 | - "*.rst" 25 | - "cmd" 26 | - "client" 27 | - "contrib" 28 | - "docs" 29 | - "proto" 30 | - "tests/e2e" 31 | - "app/app_helpers.go" 32 | - "app/sim" 33 | - "app/upgrades" -------------------------------------------------------------------------------- /proto/atomone/gov/module/v1/module.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package atomone.gov.module.v1; 4 | 5 | import "cosmos/app/v1alpha1/module.proto"; 6 | 7 | option go_package = "github.com/atomone-hub/atomone/x/gov/types/module"; 8 | 9 | // Module is the config object of the gov module. 10 | message Module { 11 | option (cosmos.app.v1alpha1.module) = { 12 | go_import : "github.com/atomone-hub/atomone/x/gov" 13 | }; 14 | 15 | // max_metadata_len defines the maximum proposal metadata length. 16 | // Defaults to 255 if not explicitly set. 17 | uint64 max_metadata_len = 1; 18 | 19 | // authority defines the custom module authority. If not set, defaults to the 20 | // governance module. 21 | string authority = 2; 22 | } 23 | -------------------------------------------------------------------------------- /app/upgrades/v4/constants.go: -------------------------------------------------------------------------------- 1 | package v4 2 | 3 | import ( 4 | store "cosmossdk.io/store/types" 5 | 6 | "github.com/atomone-hub/atomone/app/upgrades" 7 | coredaostypes "github.com/atomone-hub/atomone/x/coredaos/types" 8 | ) 9 | 10 | const ( 11 | UpgradeName = "v4" 12 | capabilityStoreKey = "capability" 13 | ) 14 | 15 | var Upgrade = upgrades.Upgrade{ 16 | UpgradeName: UpgradeName, 17 | CreateUpgradeHandler: CreateUpgradeHandler, 18 | StoreUpgrades: store.StoreUpgrades{ 19 | Added: []string{ 20 | // new module added in v4 21 | coredaostypes.ModuleName, 22 | // x/gov has been added but it uses the same store key as the x/gov fork from v3 23 | }, 24 | Deleted: []string{ 25 | capabilityStoreKey, 26 | }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - release/** 7 | - feat/** 8 | pull_request: 9 | permissions: 10 | contents: read 11 | jobs: 12 | golangci: 13 | name: golangci-lint 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/setup-go@v5 18 | with: 19 | go-version-file: go.mod 20 | - uses: technote-space/get-diff-action@v6.1.2 21 | id: git_diff 22 | with: 23 | PATTERNS: | 24 | **/*.go 25 | go.mod 26 | go.sum 27 | **/go.mod 28 | **/go.sum 29 | - name: run linting 30 | if: env.GIT_DIFF 31 | run: | 32 | make lint 33 | -------------------------------------------------------------------------------- /x/photon/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/atomone-hub/atomone/x/photon/types" 7 | ) 8 | 9 | // GetParams get all parameters as types.Params 10 | func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { 11 | store := ctx.KVStore(k.storeKey) 12 | bz := store.Get(types.ParamsKey) 13 | if bz == nil { 14 | return params 15 | } 16 | k.cdc.MustUnmarshal(bz, ¶ms) 17 | return params 18 | } 19 | 20 | // SetParams set the params 21 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error { 22 | store := ctx.KVStore(k.storeKey) 23 | bz, err := k.cdc.Marshal(¶ms) 24 | if err != nil { 25 | return err 26 | } 27 | store.Set(types.ParamsKey, bz) 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /app/genesis_account_fuzz_test.go: -------------------------------------------------------------------------------- 1 | package atomone 2 | 3 | import ( 4 | "runtime/debug" 5 | "testing" 6 | 7 | "github.com/google/gofuzz" 8 | ) 9 | 10 | func TestFuzzGenesisAccountValidate(t *testing.T) { 11 | if testing.Short() { 12 | t.Skip("running in -short mode") 13 | } 14 | 15 | t.Parallel() 16 | 17 | acct := new(SimGenesisAccount) 18 | i := 0 19 | defer func() { 20 | r := recover() 21 | if r == nil { 22 | return 23 | } 24 | 25 | // Otherwise report on the configuration and iteration. 26 | t.Fatalf("Failed SimGenesisAccount on iteration #%d: %#v\n\n%s\n\n%s", i, acct, r, debug.Stack()) 27 | }() 28 | 29 | f := fuzz.New() 30 | for i = 0; i < 1e5; i++ { 31 | acct = new(SimGenesisAccount) 32 | f.Fuzz(acct) 33 | acct.Validate() //nolint:errcheck 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /proto/scripts/protoc-swagger-gen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | cd proto 6 | # Generate atomone & cosmos-sdj swagger files 7 | # We don't care about filtering query.proto or service.proto files, because 8 | # client/docs/config.json has a white list of the required files. 9 | buf generate --template buf.gen.swagger.yaml 10 | buf generate --template buf.gen.swagger.yaml buf.build/cosmos/cosmos-sdk 11 | 12 | # combine swagger files 13 | # uses nodejs package `swagger-combine`. 14 | # all the individual swagger files need to be configured in `config.json` for merging 15 | swagger-combine ../client/docs/config.json -o ../client/docs/swagger-ui/swagger.yaml -f yaml --continueOnConflictingPaths true --includeDefinitions true 16 | 17 | # clean swagger files 18 | rm -rf ./tmp-swagger-gen 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue Template 3 | about: Basic template for issues (used by the team) 4 | labels: needs-triage 5 | --- 6 | 7 | 12 | 13 | # Problem 14 | 15 | 16 | 17 | # Closing criteria 18 | 19 | 20 | 21 | 22 | # Problem details 23 | 24 | 25 | -------------------------------------------------------------------------------- /x/dynamicfee/types/msgs_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | 10 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 11 | ) 12 | 13 | func TestMsgUpdateParams(t *testing.T) { 14 | t.Run("should reject a message with an invalid authority address", func(t *testing.T) { 15 | msg := types.NewMsgUpdateParams("invalid", types.DefaultParams()) 16 | err := msg.ValidateBasic() 17 | require.Error(t, err) 18 | }) 19 | 20 | t.Run("should accept an empty message with a valid authority address", func(t *testing.T) { 21 | msg := types.NewMsgUpdateParams(sdk.AccAddress("test").String(), types.DefaultParams()) 22 | err := msg.ValidateBasic() 23 | require.NoError(t, err) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /x/photon/genesis.go: -------------------------------------------------------------------------------- 1 | package photon 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/atomone-hub/atomone/x/photon/keeper" 9 | "github.com/atomone-hub/atomone/x/photon/types" 10 | ) 11 | 12 | // InitGenesis initializes the module's state from a provided genesis state. 13 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { 14 | if err := k.SetParams(ctx, genState.Params); err != nil { 15 | panic(fmt.Sprintf("%s module params has not been set", types.ModuleName)) 16 | } 17 | } 18 | 19 | // ExportGenesis returns the module's exported genesis 20 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 21 | genesis := types.DefaultGenesis() 22 | genesis.Params = k.GetParams(ctx) 23 | return genesis 24 | } 25 | -------------------------------------------------------------------------------- /x/coredaos/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | "github.com/atomone-hub/atomone/x/coredaos/types" 12 | ) 13 | 14 | var _ types.QueryServer = Querier{} 15 | 16 | type Querier struct { 17 | Keeper 18 | } 19 | 20 | func NewQuerier(keeper Keeper) Querier { 21 | return Querier{Keeper: keeper} 22 | } 23 | 24 | func (k Querier) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 25 | if req == nil { 26 | return nil, status.Error(codes.InvalidArgument, "invalid request") 27 | } 28 | ctx := sdk.UnwrapSDKContext(goCtx) 29 | 30 | return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil 31 | } 32 | -------------------------------------------------------------------------------- /proto/buf.yaml: -------------------------------------------------------------------------------- 1 | # Generated by "buf config migrate-v1beta1". Edit as necessary, and 2 | # remove this comment when you're finished. 3 | # 4 | # This module represents the "proto" root found in 5 | # the previous configuration. 6 | version: v1 7 | name: buf.build/atomone-hub/atomone 8 | deps: 9 | - buf.build/cosmos/cosmos-sdk:v0.50.0 10 | - buf.build/cosmos/cosmos-proto 11 | - buf.build/cosmos/gogo-proto 12 | - buf.build/googleapis/googleapis 13 | - buf.build/protocolbuffers/wellknowntypes 14 | 15 | breaking: 16 | use: 17 | - FILE 18 | lint: 19 | use: 20 | - DEFAULT 21 | - COMMENTS 22 | - FILE_LOWER_SNAKE_CASE 23 | except: 24 | - UNARY_RPC 25 | - COMMENT_FIELD 26 | - SERVICE_SUFFIX 27 | - PACKAGE_VERSION_SUFFIX 28 | - RPC_REQUEST_STANDARD_NAME 29 | ignore: 30 | - tendermint 31 | -------------------------------------------------------------------------------- /x/photon/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/atomone-hub/atomone/x/photon/types" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestGenesisState_Validate(t *testing.T) { 11 | tests := []struct { 12 | desc string 13 | genState *types.GenesisState 14 | valid bool 15 | }{ 16 | { 17 | desc: "default is valid", 18 | genState: types.DefaultGenesis(), 19 | valid: true, 20 | }, 21 | { 22 | desc: "valid genesis state", 23 | genState: &types.GenesisState{}, 24 | valid: true, 25 | }, 26 | } 27 | for _, tc := range tests { 28 | t.Run(tc.desc, func(t *testing.T) { 29 | err := tc.genState.Validate() 30 | if tc.valid { 31 | require.NoError(t, err) 32 | } else { 33 | require.Error(t, err) 34 | } 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /x/photon/types/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // NewParams creates a new Params instance 4 | func NewParams(mintDisabled bool, txFeeExceptions []string) Params { 5 | return Params{ 6 | MintDisabled: mintDisabled, 7 | TxFeeExceptions: txFeeExceptions, 8 | } 9 | } 10 | 11 | const ( 12 | defaultMintDisabled = false 13 | ) 14 | 15 | // NOTE(tb): Not possible to use `sdk.MsgTypeURL(types.MsgMintPhoton{})` 16 | // instead of plain text because at this step the msg is not registered yet. 17 | var defaultTxFeeExceptions = []string{"/atomone.photon.v1.MsgMintPhoton"} 18 | 19 | // DefaultParams returns a default set of parameters 20 | func DefaultParams() Params { 21 | return NewParams(defaultMintDisabled, defaultTxFeeExceptions) 22 | } 23 | 24 | // Validate validates the set of params 25 | func (p Params) ValidateBasic() error { 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /app/params/config.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | const ( 4 | BondDenom = "uatone" 5 | 6 | Bech32PrefixAccAddr = "atone" 7 | ) 8 | 9 | var ( 10 | // Bech32PrefixAccPub defines the Bech32 prefix of an account's public key. 11 | Bech32PrefixAccPub = Bech32PrefixAccAddr + "pub" 12 | // Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address. 13 | Bech32PrefixValAddr = Bech32PrefixAccAddr + "valoper" 14 | // Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key. 15 | Bech32PrefixValPub = Bech32PrefixAccAddr + "valoperpub" 16 | // Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address. 17 | Bech32PrefixConsAddr = Bech32PrefixAccAddr + "valcons" 18 | // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key. 19 | Bech32PrefixConsPub = Bech32PrefixAccAddr + "valconspub" 20 | ) 21 | -------------------------------------------------------------------------------- /x/coredaos/genesis.go: -------------------------------------------------------------------------------- 1 | package coredaos 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/atomone-hub/atomone/x/coredaos/keeper" 9 | "github.com/atomone-hub/atomone/x/coredaos/types" 10 | ) 11 | 12 | // InitGenesis initializes the module's state from a provided genesis state. 13 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { 14 | if err := genState.Validate(); err != nil { 15 | panic(err) 16 | } 17 | 18 | if err := k.Params.Set(ctx, genState.Params); err != nil { 19 | panic(fmt.Sprintf("%s module params has not been set", types.ModuleName)) 20 | } 21 | } 22 | 23 | // ExportGenesis returns the module's exported genesis 24 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 25 | params := k.GetParams(ctx) 26 | return types.NewGenesisState(params) 27 | } 28 | -------------------------------------------------------------------------------- /x/photon/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/cosmos/cosmos-sdk/codec/legacy" 6 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/msgservice" 9 | ) 10 | 11 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 12 | legacy.RegisterAminoMsg(cdc, &MsgMintPhoton{}, "atomone/photon/v1/MsgMintPhoton") 13 | legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "atomone/x/photon/v1/MsgUpdateParams") 14 | cdc.RegisterConcrete(&Params{}, "atomone/photon/v1/Params", nil) 15 | } 16 | 17 | func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 18 | registry.RegisterImplementations((*sdk.Msg)(nil), 19 | &MsgMintPhoton{}, &MsgUpdateParams{}, 20 | ) 21 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 22 | } 23 | -------------------------------------------------------------------------------- /tests/e2e/address.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "strconv" 7 | 8 | "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" 9 | crypto "github.com/cosmos/cosmos-sdk/crypto/types" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | // HDPath generates an HD path based on the wallet index 14 | func HDPath(index int) string { 15 | return fmt.Sprintf("m/44'/118'/0'/0/%d", index) 16 | } 17 | 18 | // PubKey returns a sample account PubKey 19 | func PubKey() crypto.PubKey { 20 | seed := []byte(strconv.Itoa(rand.Int())) 21 | return ed25519.GenPrivKeyFromSecret(seed).PubKey() 22 | } 23 | 24 | // AccAddress returns a sample account address 25 | func AccAddress() sdk.AccAddress { 26 | addr := PubKey().Address() 27 | return sdk.AccAddress(addr) 28 | } 29 | 30 | // Address returns a sample string account address 31 | func Address() string { 32 | return AccAddress().String() 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Release" 2 | 3 | on: 4 | # can be used to re-release an existing tag 5 | workflow_dispatch: 6 | 7 | push: 8 | tags: 9 | - "v[0-9]+\\.[0-9]+\\.[0-9]+" 10 | - "v[0-9]+\\.[0-9]+\\.[0-9]+-rc[0-9]+" 11 | 12 | jobs: 13 | release: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | - run: git fetch --force --tags 21 | 22 | - uses: actions/setup-go@v5 23 | with: 24 | go-version-file: go.mod 25 | 26 | - name: Set Env 27 | run: echo "TM_VERSION=$(make print_tm_version)" >> $GITHUB_ENV 28 | 29 | - name: Release 30 | uses: goreleaser/goreleaser-action@v5 31 | with: 32 | version: v1.25.1 33 | args: release --clean 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /x/dynamicfee/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/cosmos/cosmos-sdk/codec/legacy" 6 | "github.com/cosmos/cosmos-sdk/codec/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/msgservice" 9 | ) 10 | 11 | // RegisterLegacyAminoCodec registers the necessary x/dynamicfee interfaces (messages) on the 12 | // provided LegacyAmino codec. 13 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 14 | legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "atomone/x/dynamicfee/v1/MsgUpdateParams") 15 | } 16 | 17 | // RegisterInterfaces registers the x/dynamicfee interfaces (messages + msg server) on the 18 | // provided InterfaceRegistry. 19 | func RegisterInterfaces(registry types.InterfaceRegistry) { 20 | registry.RegisterImplementations((*sdk.Msg)(nil), 21 | &MsgUpdateParams{}, 22 | ) 23 | 24 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 25 | } 26 | -------------------------------------------------------------------------------- /tests/e2e/io.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | ) 8 | 9 | // copyFile copy file from src to dst 10 | func copyFile(src, dst string) (int64, error) { 11 | sourceFileStat, err := os.Stat(src) 12 | if err != nil { 13 | return 0, err 14 | } 15 | 16 | if !sourceFileStat.Mode().IsRegular() { 17 | return 0, fmt.Errorf("%s is not a regular file", src) 18 | } 19 | 20 | source, err := os.Open(src) 21 | if err != nil { 22 | return 0, err 23 | } 24 | defer source.Close() 25 | 26 | destination, err := os.Create(dst) 27 | if err != nil { 28 | return 0, err 29 | } 30 | defer destination.Close() 31 | 32 | nBytes, err := io.Copy(destination, source) 33 | return nBytes, err 34 | } 35 | 36 | // writeFile write a byte slice into a file path 37 | // create the file if it doesn't exist 38 | // NOTE: this file can be write and read by everyone 39 | func writeFile(path string, body []byte) error { 40 | return os.WriteFile(path, body, 0o666) //nolint:gosec 41 | } 42 | -------------------------------------------------------------------------------- /post/post.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | 9 | dynamicfeepost "github.com/atomone-hub/atomone/x/dynamicfee/post" 10 | ) 11 | 12 | // PostHandlerOptions are the options required for constructing a Dynamicfee PostHandler. 13 | type HandlerOptions struct { 14 | DynamicfeeKeeper dynamicfeepost.DynamicfeeKeeper 15 | } 16 | 17 | // NewPostHandler returns a PostHandler chain with the fee deduct decorator. 18 | func NewPostHandler(options HandlerOptions) (sdk.PostHandler, error) { 19 | if options.DynamicfeeKeeper == nil { 20 | return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "dynamicfee keeper is required for post builder") 21 | } 22 | 23 | postDecorators := []sdk.PostDecorator{ 24 | dynamicfeepost.NewDynamicfeeStateUpdateDecorator( 25 | options.DynamicfeeKeeper, 26 | ), 27 | } 28 | 29 | return sdk.ChainPostDecorators(postDecorators...), nil 30 | } 31 | -------------------------------------------------------------------------------- /contrib/localnet/proposal_legacy_param_change.json: -------------------------------------------------------------------------------- 1 | { 2 | "messages": [ 3 | { 4 | "@type": "/atomone.gov.v1.MsgExecLegacyContent", 5 | "content": { 6 | "@type": "/cosmos.params.v1beta1.ParameterChangeProposal", 7 | "title": "IBC Transfers Enablement Proposal", 8 | "description": "This proposal would enable interchain functionality, allowing AtomOne to connect and interact seamlessly with the wider Cosmos ecosystem.", 9 | "changes": [ 10 | { 11 | "subspace": "transfer", 12 | "key": "SendEnabled", 13 | "value": "true" 14 | }, 15 | { 16 | "subspace": "transfer", 17 | "key": "ReceiveEnabled", 18 | "value": "true" 19 | } 20 | ] 21 | }, 22 | "authority": "atone10d07y265gmmuvt4z0w9aw880jnsr700j5z0zqt" 23 | } 24 | ], 25 | "metadata": "ipfs://CID", 26 | "deposit": "200000000uatone", 27 | "title": "IBC Enablement", 28 | "summary": "summary" 29 | } 30 | -------------------------------------------------------------------------------- /x/dynamicfee/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | ) 8 | 9 | // NewGenesisState returns a new genesis state for the module. 10 | func NewGenesisState( 11 | params Params, 12 | state State, 13 | ) *GenesisState { 14 | return &GenesisState{ 15 | Params: params, 16 | State: state, 17 | } 18 | } 19 | 20 | // ValidateBasic performs basic validation of the genesis state data returning an 21 | // error for any failed validation criteria. 22 | func (gs *GenesisState) ValidateBasic() error { 23 | if err := gs.Params.ValidateBasic(); err != nil { 24 | return err 25 | } 26 | return gs.State.ValidateBasic() 27 | } 28 | 29 | // GetGenesisStateFromAppState returns x/dynamicfee GenesisState given raw application 30 | // genesis state. 31 | func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) GenesisState { 32 | var gs GenesisState 33 | cdc.MustUnmarshalJSON(appState[ModuleName], &gs) 34 | return gs 35 | } 36 | -------------------------------------------------------------------------------- /x/dynamicfee/types/msgs.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | var _ sdk.Msg = &MsgUpdateParams{} 8 | 9 | // NewMsgUpdateParams returns a new message to update the x/dynamicfee module's parameters. 10 | func NewMsgUpdateParams(authority string, params Params) MsgUpdateParams { 11 | return MsgUpdateParams{ 12 | Authority: authority, 13 | Params: params, 14 | } 15 | } 16 | 17 | // GetSigners implements GetSigners for the msg. 18 | func (m *MsgUpdateParams) GetSigners() []sdk.AccAddress { 19 | addr, _ := sdk.AccAddressFromBech32(m.Authority) 20 | return []sdk.AccAddress{addr} 21 | } 22 | 23 | // ValidateBasic determines whether the information in the message is formatted correctly, specifically 24 | // whether the authority is a valid acc-address. 25 | func (m *MsgUpdateParams) ValidateBasic() error { 26 | // validate authority address 27 | _, err := sdk.AccAddressFromBech32(m.Authority) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /contrib/githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | CMDS='git go gofmt goimports misspell' 6 | STAGED_GO_FILES=$(git diff --cached --name-only -- '*.go') 7 | 8 | f_echo_stderr() { 9 | echo $@ >&2 10 | } 11 | 12 | f_exit_success() { 13 | [ x"$@" != "x" ] && f_echo_stderr $@ || exit 0 14 | } 15 | trap f_exit_success EXIT 16 | 17 | f_check_cmds() { 18 | for cmd in ${CMDS}; do 19 | which ${cmd} &>/dev/null || f_exit_success "couldn't find ${cmd}, skipping" 20 | done 21 | } 22 | 23 | f_check_cmds 24 | 25 | if [[ $STAGED_GO_FILES != "" ]]; then 26 | f_echo_stderr "[pre-commit] fmt'ing staged files..." 27 | for file in $STAGED_GO_FILES; do 28 | if [[ $file =~ vendor/ ]] || [[ $file =~ tests/mocks/ ]] || [[ $file =~ \.pb\.go ]]; then 29 | continue 30 | fi 31 | 32 | gofmt -w -s $file 33 | misspell -w $file 34 | goimports -w -local github.com/atomone-hub/atomone $file 35 | git add $file 36 | 37 | done 38 | fi 39 | 40 | # Run go mod tidy 41 | go mod tidy && git add go.mod go.sum 42 | -------------------------------------------------------------------------------- /contrib/githooks/precommit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | CMDS='git go gofmt goimports misspell' 6 | STAGED_GO_FILES=$(git diff --cached --name-only -- '*.go') 7 | 8 | f_echo_stderr() { 9 | echo $@ >&2 10 | } 11 | 12 | f_exit_success() { 13 | [ x"$@" != "x" ] && f_echo_stderr $@ || exit 0 14 | } 15 | trap f_exit_success EXIT 16 | 17 | f_check_cmds() { 18 | for cmd in ${CMDS}; do 19 | which ${cmd} &>/dev/null || f_exit_success "couldn't find ${cmd}, skipping" 20 | done 21 | } 22 | 23 | f_check_cmds 24 | 25 | if [[ $STAGED_GO_FILES != "" ]]; then 26 | f_echo_stderr "[pre-commit] fmt'ing staged files..." 27 | for file in $STAGED_GO_FILES; do 28 | if [[ $file =~ vendor/ ]] || [[ $file =~ tests/mocks/ ]] || [[ $file =~ \.pb\.go ]]; then 29 | continue 30 | fi 31 | 32 | gofmt -w -s $file 33 | misspell -w $file 34 | goimports -w -local github.com/atomone-hub/atomone $file 35 | git add $file 36 | 37 | done 38 | fi 39 | 40 | # Run go mod tidy 41 | go mod tidy && git add go.mod go.sum 42 | -------------------------------------------------------------------------------- /x/gov/types/v1/delegation.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "fmt" 5 | 6 | "cosmossdk.io/math" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | sdkgovtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 10 | ) 11 | 12 | // NewGovernanceDelegation creates a new GovernanceDelegation instance 13 | func NewGovernanceDelegation(delegatorAddr sdk.AccAddress, governorAddr sdkgovtypes.GovernorAddress) GovernanceDelegation { 14 | return GovernanceDelegation{ 15 | DelegatorAddress: delegatorAddr.String(), 16 | GovernorAddress: governorAddr.String(), 17 | } 18 | } 19 | 20 | // NewGovernorValShares creates a new GovernorValShares instance 21 | func NewGovernorValShares(governorAddr sdkgovtypes.GovernorAddress, validatorAddress sdk.ValAddress, shares math.LegacyDec) GovernorValShares { 22 | if shares.IsNegative() { 23 | panic(fmt.Sprintf("invalid governor val shares: %s", shares)) 24 | } 25 | 26 | return GovernorValShares{ 27 | GovernorAddress: governorAddr.String(), 28 | ValidatorAddress: validatorAddress.String(), 29 | Shares: shares, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us squash bugs! 4 | labels: bug, needs-triage 5 | --- 6 | 7 | 12 | 13 | ## Summary of Bug 14 | 15 | 16 | 17 | ## Version 18 | 19 | 20 | 21 | ## Steps to Reproduce 22 | 23 | 24 | 25 | ____ 26 | 27 | #### For Admin Use 28 | 29 | - [ ] Not duplicate issue 30 | - [ ] Appropriate labels applied 31 | - [ ] Appropriate contributors tagged 32 | - [ ] Contributor assigned/self-assigned 33 | - [ ] Is a spike necessary to map out how the issue should be approached? 34 | 35 | -------------------------------------------------------------------------------- /proto/atomone/coredaos/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.coredaos.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "cosmos/base/query/v1beta1/pagination.proto"; 7 | import "atomone/coredaos/v1/coredaos.proto"; 8 | import "cosmos/base/v1beta1/coin.proto"; 9 | import "amino/amino.proto"; 10 | import "cosmos_proto/cosmos.proto"; 11 | 12 | option go_package = "github.com/atomone-hub/atomone/x/coredaos/types"; 13 | 14 | // Query defines the gRPC querier service. 15 | service Query { 16 | // Parameters queries the parameters of the module. 17 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 18 | option (google.api.http).get = "/atomone/coredaos/v1/params"; 19 | } 20 | } 21 | 22 | // QueryParamsRequest is request type for the Query/Params RPC method. 23 | message QueryParamsRequest {} 24 | 25 | // QueryParamsResponse is response type for the Query/Params RPC method. 26 | message QueryParamsResponse { 27 | // params holds all the parameters of this module. 28 | Params params = 1 [(gogoproto.nullable) = false]; 29 | } 30 | -------------------------------------------------------------------------------- /x/dynamicfee/ante/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 9 | ) 10 | 11 | type DynamicfeeKeeper interface { 12 | GetMinGasPrice(context.Context, string) (sdk.DecCoin, error) 13 | GetParams(context.Context) (types.Params, error) 14 | } 15 | 16 | // AccountKeeper defines the contract needed for AccountKeeper related APIs. 17 | // Interface provides support to use non-sdk AccountKeeper for AnteHandler's decorators. 18 | type AccountKeeper interface { 19 | GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI 20 | } 21 | 22 | // FeeGrantKeeper defines the expected feegrant keeper. 23 | type FeeGrantKeeper interface { 24 | UseGrantedFees(ctx context.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error 25 | } 26 | 27 | // BankKeeper defines the contract needed for supply related APIs. 28 | type BankKeeper interface { 29 | SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error 30 | } 31 | -------------------------------------------------------------------------------- /x/gov/types/v1/deposit.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // NewDeposit creates a new Deposit instance 10 | // 11 | //nolint:interfacer 12 | func NewDeposit(proposalID uint64, depositor sdk.AccAddress, amount sdk.Coins) Deposit { 13 | return Deposit{proposalID, depositor.String(), amount} 14 | } 15 | 16 | // Deposits is a collection of Deposit objects 17 | type Deposits []*Deposit 18 | 19 | // Equal returns true if two slices (order-dependant) of deposits are equal. 20 | func (d Deposits) Equal(other Deposits) bool { 21 | if len(d) != len(other) { 22 | return false 23 | } 24 | 25 | for i, deposit := range d { 26 | if deposit.String() != other[i].String() { 27 | return false 28 | } 29 | } 30 | 31 | return true 32 | } 33 | 34 | // String implements stringer interface 35 | func (d Deposits) String() string { 36 | if len(d) == 0 { 37 | return "[]" 38 | } 39 | out := fmt.Sprintf("Deposits for Proposal %d:", d[0].ProposalId) 40 | for _, dep := range d { 41 | out += fmt.Sprintf("\n %s: %s", dep.Depositor, dep.Amount) 42 | } 43 | return out 44 | } 45 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/deposit.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // NewDeposit creates a new Deposit instance 10 | // 11 | //nolint:interfacer 12 | func NewDeposit(proposalID uint64, depositor sdk.AccAddress, amount sdk.Coins) Deposit { 13 | return Deposit{proposalID, depositor.String(), amount} 14 | } 15 | 16 | // Deposits is a collection of Deposit objects 17 | type Deposits []Deposit 18 | 19 | // Equal returns true if two slices (order-dependant) of deposits are equal. 20 | func (d Deposits) Equal(other Deposits) bool { 21 | if len(d) != len(other) { 22 | return false 23 | } 24 | 25 | for i, deposit := range d { 26 | if deposit.String() != other[i].String() { 27 | return false 28 | } 29 | } 30 | 31 | return true 32 | } 33 | 34 | // String implements stringer interface 35 | func (d Deposits) String() string { 36 | if len(d) == 0 { 37 | return "[]" 38 | } 39 | out := fmt.Sprintf("Deposits for Proposal %d:", d[0].ProposalId) 40 | for _, dep := range d { 41 | out += fmt.Sprintf("\n %s: %s", dep.Depositor, dep.Amount) 42 | } 43 | return out 44 | } 45 | -------------------------------------------------------------------------------- /app/params/weights.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | // Default simulation operation weights for messages and gov proposals 4 | const ( 5 | DefaultWeightMsgSend int = 100 6 | DefaultWeightMsgMultiSend int = 10 7 | DefaultWeightMsgSetWithdrawAddress int = 50 8 | DefaultWeightMsgWithdrawDelegationReward int = 50 9 | DefaultWeightMsgWithdrawValidatorCommission int = 50 10 | DefaultWeightMsgFundCommunityPool int = 50 11 | DefaultWeightMsgDeposit int = 100 12 | DefaultWeightMsgVote int = 67 13 | DefaultWeightMsgUnjail int = 100 14 | DefaultWeightMsgCreateValidator int = 100 15 | DefaultWeightMsgEditValidator int = 5 16 | DefaultWeightMsgDelegate int = 100 17 | DefaultWeightMsgUndelegate int = 100 18 | DefaultWeightMsgBeginRedelegate int = 100 19 | DefaultWeightMsgCancelUnbondingDelegation int = 100 20 | 21 | DefaultWeightCommunitySpendProposal int = 5 22 | DefaultWeightTextProposal int = 5 23 | DefaultWeightParamChangeProposal int = 5 24 | ) 25 | -------------------------------------------------------------------------------- /app/app_test.go: -------------------------------------------------------------------------------- 1 | package atomone_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "cosmossdk.io/log" 9 | dbm "github.com/cosmos/cosmos-db" 10 | 11 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 12 | 13 | atomone "github.com/atomone-hub/atomone/app" 14 | atomonehelpers "github.com/atomone-hub/atomone/app/helpers" 15 | govtypes "github.com/atomone-hub/atomone/x/gov/types" 16 | ) 17 | 18 | func TestAtomOneApp_BlockedModuleAccountAddrs(t *testing.T) { 19 | app := atomone.NewAtomOneApp( 20 | log.NewNopLogger(), 21 | dbm.NewMemDB(), 22 | nil, 23 | true, 24 | atomone.EmptyAppOptions{}, 25 | ) 26 | 27 | moduleAccountAddresses := app.ModuleAccountAddrs() 28 | blockedAddrs := app.BlockedModuleAccountAddrs(moduleAccountAddresses) 29 | 30 | require.NotContains(t, blockedAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String()) 31 | } 32 | 33 | func TestAtomOneApp_Export(t *testing.T) { 34 | app := atomonehelpers.Setup(t) 35 | _, err := app.ExportAppStateAndValidators(true, []string{}, []string{}) 36 | require.NoError(t, err, "ExportAppStateAndValidators should not have an error") 37 | } 38 | -------------------------------------------------------------------------------- /x/photon/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | context "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // AccountKeeper defines the expected account keeper used for simulations (noalias) 10 | type AccountKeeper interface { 11 | GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI 12 | } 13 | 14 | // StakingKeeper defines the expected staking keeper. 15 | type StakingKeeper interface { 16 | BondDenom(context.Context) (string, error) 17 | } 18 | 19 | // BankKeeper defines the expected interface needed to retrieve account balances. 20 | type BankKeeper interface { 21 | SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins 22 | MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error 23 | BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error 24 | SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error 25 | SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error 26 | GetSupply(ctx context.Context, denom string) sdk.Coin 27 | } 28 | -------------------------------------------------------------------------------- /cmd/atomoned/cmd/tx.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client/flags" 7 | authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" 8 | ) 9 | 10 | func GetBroadCastCommand() *cobra.Command { 11 | cmd := authcmd.GetBroadcastCommand() 12 | 13 | // Hide the flags that are not needed/used for the broadcast command 14 | // but are added from the `flags.AddTxFlagsToCmd` function 15 | unusedFlags := []string{ 16 | flags.FlagFrom, 17 | flags.FlagAccountNumber, 18 | flags.FlagSequence, 19 | flags.FlagNote, 20 | flags.FlagFees, 21 | flags.FlagGasPrices, 22 | flags.FlagUseLedger, 23 | flags.FlagGasAdjustment, 24 | flags.FlagDryRun, 25 | flags.FlagGenerateOnly, 26 | flags.FlagOffline, 27 | flags.FlagSkipConfirmation, 28 | flags.FlagSignMode, 29 | flags.FlagTimeoutHeight, 30 | flags.FlagFeePayer, 31 | flags.FlagFeeGranter, 32 | flags.FlagTip, 33 | flags.FlagAux, 34 | flags.FlagChainID, 35 | flags.FlagGas, 36 | flags.FlagKeyringDir, 37 | flags.FlagKeyringBackend, 38 | } 39 | 40 | for _, flag := range unusedFlags { 41 | _ = cmd.Flags().MarkHidden(flag) 42 | } 43 | 44 | return cmd 45 | } 46 | -------------------------------------------------------------------------------- /pkg/address/address_test.go: -------------------------------------------------------------------------------- 1 | package address 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestConvertBech32Prefix(t *testing.T) { 11 | cases := []struct { 12 | name string 13 | address string 14 | prefix string 15 | converted string 16 | err error 17 | }{ 18 | { 19 | name: "Convert valid bech 32 address", 20 | address: "akash1a6zlyvpnksx8wr6wz8wemur2xe8zyh0ytz6d88", 21 | converted: "cosmos1a6zlyvpnksx8wr6wz8wemur2xe8zyh0yxeh27a", 22 | prefix: "cosmos", 23 | }, 24 | { 25 | name: "Convert invalid address", 26 | address: "invalidaddress", 27 | prefix: "cosmos", 28 | err: errors.New("cannot decode invalidaddress address: decoding bech32 failed: invalid separator index -1"), 29 | }, 30 | } 31 | 32 | for _, tt := range cases { 33 | t.Run(tt.name, func(t *testing.T) { 34 | convertedAddress, err := ConvertBech32Prefix(tt.address, tt.prefix) 35 | if tt.err != nil { 36 | require.ErrorContains(t, err, tt.err.Error()) 37 | } else { 38 | require.NoError(t, err) 39 | } 40 | require.Equal(t, tt.converted, convertedAddress) 41 | }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /x/photon/module_simulation.go: -------------------------------------------------------------------------------- 1 | package photon 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/types/module" 5 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 6 | 7 | "github.com/atomone-hub/atomone/x/photon/simulation" 8 | "github.com/atomone-hub/atomone/x/photon/types" 9 | ) 10 | 11 | // GenerateGenesisState creates a randomized GenState of the module. 12 | func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 13 | simulation.RandomizedGenState(simState) 14 | } 15 | 16 | // RegisterStoreDecoder registers a decoder. 17 | func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { 18 | sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) 19 | } 20 | 21 | func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { 22 | return simulation.ProposalMsgs() 23 | } 24 | 25 | // WeightedOperations returns the all the module operations with their respective weights. 26 | func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { 27 | return simulation.WeightedOperations(simState.AppParams, simState.Cdc, 28 | am.accountKeeper, am.bankKeeper, am.stakingKeeper, am.keeper) 29 | } 30 | -------------------------------------------------------------------------------- /contrib/Dockerfile.test: -------------------------------------------------------------------------------- 1 | # Simple usage with a mounted data directory: 2 | # > docker build -t atomone . 3 | # > docker run -it -p 46657:46657 -p 46656:46656 -v ~/.atomone:/root/.atomone atomone atomoned init 4 | # > docker run -it -p 46657:46657 -p 46656:46656 -v ~/.atomone:/root/.atomone atomone atomoned start 5 | FROM golang:1.22-alpine AS build-env 6 | 7 | # Set up dependencies 8 | ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 9 | 10 | # Set working directory for the build 11 | WORKDIR /go/src/github.com/atomone-hub/atomone 12 | 13 | # Add source files 14 | COPY . . 15 | 16 | # Install minimum necessary dependencies, build Cosmos SDK, remove packages 17 | RUN apk add --no-cache $PACKAGES && \ 18 | make install 19 | 20 | # Final image 21 | FROM alpine:edge 22 | 23 | # Install ca-certificates 24 | RUN apk add --update ca-certificates 25 | WORKDIR /root 26 | 27 | # Copy over binaries from the build-env 28 | COPY --from=build-env /go/bin/atomoned /usr/bin/atomoned 29 | 30 | COPY ./contrib/single-node.sh . 31 | 32 | EXPOSE 26657 33 | 34 | ENTRYPOINT [ "./single-node.sh" ] 35 | # NOTE: to run this image, docker run -d -p 26657:26657 ./single-node.sh {{chain_id}} {{genesis_account}} 36 | -------------------------------------------------------------------------------- /x/coredaos/module_simulation.go: -------------------------------------------------------------------------------- 1 | package coredaos 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/types/module" 5 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 6 | 7 | "github.com/atomone-hub/atomone/x/coredaos/simulation" 8 | "github.com/atomone-hub/atomone/x/coredaos/types" 9 | ) 10 | 11 | // GenerateGenesisState creates a randomized GenState of the module. 12 | func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 13 | simulation.RandomizedGenState(simState) 14 | } 15 | 16 | // RegisterStoreDecoder registers a decoder. 17 | func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { 18 | sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) 19 | } 20 | 21 | func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { 22 | return simulation.ProposalMsgs() 23 | } 24 | 25 | // WeightedOperations returns the all the module operations with their respective weights. 26 | func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { 27 | return simulation.WeightedOperations(simState.AppParams, simState.Cdc, 28 | am.govKeeper, am.stakingKeeper, am.accountKeeper, am.bankKeeper, am.keeper) 29 | } 30 | -------------------------------------------------------------------------------- /x/coredaos/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/cosmos/cosmos-sdk/codec/legacy" 6 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/msgservice" 9 | ) 10 | 11 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 12 | legacy.RegisterAminoMsg(cdc, &MsgAnnotateProposal{}, "atomone/v1/MsgAnnotateProposal") 13 | legacy.RegisterAminoMsg(cdc, &MsgEndorseProposal{}, "atomone/v1/MsgEndorseProposal") 14 | legacy.RegisterAminoMsg(cdc, &MsgExtendVotingPeriod{}, "atomone/v1/MsgExtendVotingPeriod") 15 | legacy.RegisterAminoMsg(cdc, &MsgVetoProposal{}, "atomone/v1/MsgVetoProposal") 16 | legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "atomone/x/coredaos/v1/MsgUpdateParams") 17 | cdc.RegisterConcrete(&Params{}, "atomone/coredaos/v1/Params", nil) 18 | } 19 | 20 | func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 21 | registry.RegisterImplementations((*sdk.Msg)(nil), 22 | &MsgAnnotateProposal{}, &MsgEndorseProposal{}, &MsgExtendVotingPeriod{}, &MsgVetoProposal{}, &MsgUpdateParams{}, 23 | ) 24 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 25 | } 26 | -------------------------------------------------------------------------------- /proto/atomone/coredaos/v1/coredaos.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.coredaos.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/protobuf/duration.proto"; 6 | import "cosmos_proto/cosmos.proto"; 7 | 8 | option go_package = "github.com/atomone-hub/atomone/x/coredaos/types"; 9 | 10 | // Params defines the parameters for the x/coredaos module. 11 | message Params { 12 | // steering_dao_address defines the address which has authority 13 | // to execute messages as Steering DAO. 14 | string steering_dao_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; 15 | 16 | // oversight_dao_address defines the address which has authority 17 | // to execute messages as Oversight DAO. 18 | string oversight_dao_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; 19 | 20 | // voting_period_extensions_limit defines the maximum number of times 21 | // a proposal's voting period can be extended. 22 | uint32 voting_period_extensions_limit = 3; 23 | 24 | // voting_period_extension_duration defines the duration for which 25 | // a proposal's voting period can be extended. 26 | google.protobuf.Duration voting_period_extension_duration = 4 [(gogoproto.stdduration) = true]; 27 | } 28 | -------------------------------------------------------------------------------- /x/gov/types/v1/content.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/gogoproto/proto" 7 | 8 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 9 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 10 | 11 | "github.com/atomone-hub/atomone/x/gov/types/v1beta1" 12 | ) 13 | 14 | // NewLegacyContent creates a new MsgExecLegacyContent from a legacy Content 15 | // interface. 16 | func NewLegacyContent(content v1beta1.Content, authority string) (*MsgExecLegacyContent, error) { 17 | msg, ok := content.(proto.Message) 18 | if !ok { 19 | return nil, fmt.Errorf("%T does not implement proto.Message", content) 20 | } 21 | 22 | any, err := codectypes.NewAnyWithValue(msg) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | return NewMsgExecLegacyContent(any, authority), nil 28 | } 29 | 30 | // LegacyContentFromMessage extracts the legacy Content interface from a 31 | // MsgExecLegacyContent. 32 | func LegacyContentFromMessage(msg *MsgExecLegacyContent) (v1beta1.Content, error) { 33 | content, ok := msg.Content.GetCachedValue().(v1beta1.Content) 34 | if !ok { 35 | return nil, sdkerrors.ErrInvalidType.Wrapf("expected %T, got %T", (*v1beta1.Content)(nil), msg.Content.GetCachedValue()) 36 | } 37 | 38 | return content, nil 39 | } 40 | -------------------------------------------------------------------------------- /.github/workflows/sim-label.yml: -------------------------------------------------------------------------------- 1 | name: SimLabeled 2 | on: 3 | pull_request: 4 | types: [ labeled ] 5 | 6 | jobs: 7 | cleanup-runs: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: rokroskar/workflow-run-cleanup-action@master 11 | env: 12 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 13 | # if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'" 14 | 15 | newbuild: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/setup-go@v5 19 | - name: Install runsim 20 | run: go install github.com/cosmos/tools/cmd/runsim@v1.0.0 21 | - uses: actions/cache@v4 22 | with: 23 | path: ~/go/bin 24 | key: ${{ runner.os }}-go-runsim-binary 25 | 26 | test-sim-nondeterminism-labeled: 27 | if: ${{ github.event.label.name == 'sim' }} 28 | runs-on: ubuntu-latest 29 | needs: newbuild 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: actions/setup-go@v5 33 | with: 34 | go-version-file: go.mod 35 | - uses: actions/cache@v4 36 | with: 37 | path: ~/go/bin 38 | key: ${{ runner.os }}-go-runsim-binary 39 | - name: test nondeterminism 40 | run: | 41 | make test-sim-nondeterminism 42 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/content.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // Content defines an interface that a proposal must implement. It contains 8 | // information such as the title and description along with the type and routing 9 | // information for the appropriate handler to process the proposal. Content can 10 | // have additional fields, which will handled by a proposal's Handler. 11 | type Content interface { 12 | GetTitle() string 13 | GetDescription() string 14 | ProposalRoute() string 15 | ProposalType() string 16 | ValidateBasic() error 17 | String() string 18 | } 19 | 20 | // Handler defines a function that handles a proposal after it has passed the 21 | // governance process. 22 | type Handler func(ctx sdk.Context, content Content) error 23 | 24 | // WrapSDKHandler converts a Cosmos SDK gov Handler to GovGen gov Handler 25 | func WrapSDKHandler(sdkHandler Handler) Handler { 26 | return func(ctx sdk.Context, content Content) error { 27 | return sdkHandler(ctx, content) 28 | } 29 | } 30 | 31 | type HandlerRoute struct { 32 | Handler Handler 33 | RouteKey string 34 | } 35 | 36 | // IsManyPerContainerType implements the depinject.ManyPerContainerType interface. 37 | func (HandlerRoute) IsManyPerContainerType() {} 38 | -------------------------------------------------------------------------------- /docs/architecture/demo/README_NakamotoBonus.md: -------------------------------------------------------------------------------- 1 | # Nakamoto Bonus Demo 2 | 3 | The `NakamotoBonus.ipynb` demo showcases the effect of assigning the block reward in a proportional and in a uniform way. The user is able to change using a widget the state of the delegations on the network and amount of the reward that is assigned proportionally vs uniformly and see how this affects the way reward is split across validators. 4 | It can be seen that, increasing the amount of reward that is assigned uniformly - i.e. the Nakamoto Bonus - increases the incentive of delegators to delegate on validators having less voting power. 5 | 6 | ## Requirements 7 | 8 | The file `NakamotoBonus.ipynb` is a Jupyter notebook file and it requires python and jupyterlab to be installed in the system. There are several ways to install Jupyter lab, for more information refer to this [link](https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html). 9 | 10 | ## Usage 11 | 12 | Jupyter should be launched using the terminal from the folder containing the file `NakamotoBonus.ipynb`. 13 | 14 | ```bash 15 | jupyter lab 16 | ``` 17 | 18 | This will launch the jupyter webui. The user can then select the `NakamotoBonus.ipynb` using the file browser on the left side of the UI, and execute the code in the cells to generate the charts. 19 | -------------------------------------------------------------------------------- /contrib/single-node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -o errexit -o nounset 4 | 5 | CHAINID=$1 6 | GENACCT=$2 7 | 8 | if [ -z "$1" ]; then 9 | echo "Need to input chain id..." 10 | exit 1 11 | fi 12 | 13 | if [ -z "$2" ]; then 14 | echo "Need to input genesis account address..." 15 | exit 1 16 | fi 17 | 18 | # Build genesis file incl account for passed address 19 | coins="10000000000stake,100000000000samoleans" 20 | atomoned init --chain-id $CHAINID $CHAINID 21 | atomoned keys add validator --keyring-backend="test" 22 | atomoned add-genesis-account $(atomoned keys show validator -a --keyring-backend="test") $coins 23 | atomoned add-genesis-account $GENACCT $coins 24 | atomoned gentx validator 5000000000stake --keyring-backend="test" --chain-id $CHAINID 25 | atomoned collect-gentxs 26 | 27 | # Set proper defaults and change ports 28 | echo "Setting rpc listen address" 29 | sed -i '' 's#"tcp://127.0.0.1:26657"#"tcp://0.0.0.0:26657"#g' ~/.atomone/config/config.toml 30 | echo 2 31 | sed -i '' 's/timeout_commit = "5s"/timeout_commit = "1s"/g' ~/.atomone/config/config.toml 32 | sed -i '' 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ~/.atomone/config/config.toml 33 | sed -i '' 's/index_all_keys = false/index_all_keys = true/g' ~/.atomone/config/config.toml 34 | 35 | # Start the atomone 36 | atomoned start --pruning=nothing 37 | -------------------------------------------------------------------------------- /x/dynamicfee/module_simulation.go: -------------------------------------------------------------------------------- 1 | package dynamicfee 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/types/module" 7 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 8 | 9 | "github.com/atomone-hub/atomone/x/dynamicfee/simulation" 10 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 11 | ) 12 | 13 | // GenerateGenesisState returns a disabled dynamicfee module because the module 14 | // does not work well with simulations. Especially the dynamicfee ante handler 15 | // does not accept 0 fee coins which is quite common during simulation's 16 | // operations. 17 | func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 18 | params := types.DefaultParams() 19 | params.Enabled = false 20 | genesis := types.NewGenesisState(params, types.DefaultState()) 21 | simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(genesis) 22 | fmt.Println("Dynamicfee module is disabled") 23 | } 24 | 25 | // RegisterStoreDecoder registers a decoder. 26 | func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { 27 | sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) 28 | } 29 | 30 | // WeightedOperations returns the all the module operations with their respective weights. 31 | func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /x/photon/simulation/proposals.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/types/address" 8 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 9 | "github.com/cosmos/cosmos-sdk/x/simulation" 10 | 11 | "github.com/atomone-hub/atomone/x/photon/types" 12 | ) 13 | 14 | // Simulation operation weights constants 15 | const ( 16 | DefaultWeightMsgUpdateParams int = 100 17 | 18 | OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec 19 | ) 20 | 21 | // ProposalMsgs defines the module weighted proposals' contents 22 | func ProposalMsgs() []simtypes.WeightedProposalMsg { 23 | return []simtypes.WeightedProposalMsg{ 24 | simulation.NewWeightedProposalMsg( 25 | OpWeightMsgUpdateParams, 26 | DefaultWeightMsgUpdateParams, 27 | SimulateMsgUpdateParams, 28 | ), 29 | } 30 | } 31 | 32 | // SimulateMsgUpdateParams returns a random MsgUpdateParams 33 | func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg { 34 | // use the default gov module account address as authority 35 | var authority sdk.AccAddress = address.Module("gov") 36 | 37 | params := types.DefaultParams() 38 | params.MintDisabled = r.Intn(2) == 0 39 | return &types.MsgUpdateParams{ 40 | Authority: authority.String(), 41 | Params: params, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ue 4 | 5 | # Expect the following envvars to be set: 6 | # - APP 7 | # - VERSION 8 | # - COMMIT 9 | # - TARGET_OS 10 | # - LEDGER_ENABLED 11 | # - DEBUG 12 | 13 | # Source builder's functions library 14 | . /usr/local/share/tendermint/buildlib.sh 15 | 16 | # These variables are now available 17 | # - BASEDIR 18 | # - OUTDIR 19 | 20 | # Build for each os-architecture pair 21 | for platform in ${TARGET_PLATFORMS} ; do 22 | # This function sets GOOS, GOARCH, and OS_FILE_EXT environment variables 23 | # according to the build target platform. OS_FILE_EXT is empty in all 24 | # cases except when the target platform is 'windows'. 25 | setup_build_env_for_platform "${platform}" 26 | 27 | make clean 28 | echo Building for $(go env GOOS)/$(go env GOARCH) >&2 29 | GOROOT_FINAL="$(go env GOROOT)" \ 30 | make build \ 31 | LDFLAGS=-buildid=${VERSION} \ 32 | VERSION=${VERSION} \ 33 | COMMIT=${COMMIT} \ 34 | LEDGER_ENABLED=${LEDGER_ENABLED} 35 | mv ./build/${APP}${OS_FILE_EXT} ${OUTDIR}/${APP}-${VERSION}-$(go env GOOS)-$(go env GOARCH)${OS_FILE_EXT} 36 | 37 | # This function restore the build environment variables to their 38 | # original state. 39 | restore_build_env 40 | done 41 | 42 | # Generate and display build report. 43 | generate_build_report 44 | cat ${OUTDIR}/build_report 45 | -------------------------------------------------------------------------------- /x/dynamicfee/keeper/genesis.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 7 | ) 8 | 9 | // InitGenesis initializes the dynamicfee module's state from a given genesis state. 10 | func (k *Keeper) InitGenesis(ctx sdk.Context, gs types.GenesisState) { 11 | if err := gs.ValidateBasic(); err != nil { 12 | panic(err) 13 | } 14 | 15 | if gs.Params.Window != uint64(len(gs.State.Window)) { 16 | panic("genesis state and parameters do not match for window") 17 | } 18 | 19 | // Initialize the dynamic fee pricing state and parameters. 20 | if err := k.SetParams(ctx, gs.Params); err != nil { 21 | panic(err) 22 | } 23 | 24 | if err := k.SetState(ctx, gs.State); err != nil { 25 | panic(err) 26 | } 27 | 28 | // always init enabled height to -1 until it is explicitly set later in the application 29 | k.SetEnabledHeight(ctx, -1) 30 | } 31 | 32 | // ExportGenesis returns a GenesisState for a given context. 33 | func (k *Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { 34 | // Get the dynamicfee module's parameters. 35 | params, err := k.GetParams(ctx) 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | // Get the dynamicfee module's state. 41 | state, err := k.GetState(ctx) 42 | if err != nil { 43 | panic(err) 44 | } 45 | 46 | return types.NewGenesisState(params, state) 47 | } 48 | -------------------------------------------------------------------------------- /x/photon/keeper/resolver.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | "github.com/atomone-hub/atomone/x/photon/types" 10 | ) 11 | 12 | // ConvertToDenom returns "coin.Amount denom" for all coins that are not the denom. 13 | func (k Keeper) ConvertToDenom(ctx context.Context, coin sdk.DecCoin, denom string) (sdk.DecCoin, error) { 14 | if coin.Denom == denom { 15 | return coin, nil 16 | } 17 | 18 | bondDenom, err := k.stakingKeeper.BondDenom(ctx) 19 | if err != nil { 20 | return sdk.DecCoin{}, err 21 | } 22 | 23 | if denom == bondDenom { 24 | // use the conversion rate to convert bond denom to photon 25 | bondDenomSupply := k.bankKeeper.GetSupply(ctx, denom).Amount.ToLegacyDec() 26 | uphotonSupply := k.bankKeeper.GetSupply(ctx, types.Denom).Amount.ToLegacyDec() 27 | conversionRate := k.PhotonConversionRate(ctx, bondDenomSupply, uphotonSupply) 28 | 29 | // convert bond denom to photon 30 | amount := coin.Amount.Quo(conversionRate) 31 | return sdk.NewDecCoinFromDec(denom, amount), nil 32 | } 33 | 34 | return sdk.DecCoin{}, fmt.Errorf("error resolving denom") 35 | } 36 | 37 | func (k Keeper) ExtraDenoms(ctx context.Context) ([]string, error) { 38 | bondDenom, err := k.stakingKeeper.BondDenom(ctx) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | return []string{ 44 | bondDenom, 45 | }, nil 46 | } 47 | -------------------------------------------------------------------------------- /x/photon/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | "github.com/atomone-hub/atomone/x/photon/types" 12 | ) 13 | 14 | var _ types.QueryServer = Keeper{} 15 | 16 | func (k Keeper) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 17 | if req == nil { 18 | return nil, status.Error(codes.InvalidArgument, "invalid request") 19 | } 20 | ctx := sdk.UnwrapSDKContext(goCtx) 21 | 22 | return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil 23 | } 24 | 25 | // ConversionRate returns the staking denom to photon conversion ratio. 26 | func (k Keeper) ConversionRate(goCtx context.Context, req *types.QueryConversionRateRequest) (*types.QueryConversionRateResponse, error) { 27 | ctx := sdk.UnwrapSDKContext(goCtx) 28 | bondDenom, err := k.stakingKeeper.BondDenom(ctx) 29 | if err != nil { 30 | return nil, status.Error(codes.Internal, "failed to get bond denom") 31 | } 32 | stakingDenomSupply := k.bankKeeper.GetSupply(ctx, bondDenom).Amount.ToLegacyDec() 33 | uphotonSupply := k.bankKeeper.GetSupply(ctx, types.Denom).Amount.ToLegacyDec() 34 | cr := k.PhotonConversionRate(ctx, stakingDenomSupply, uphotonSupply) 35 | 36 | return &types.QueryConversionRateResponse{ConversionRate: cr.String()}, nil 37 | } 38 | -------------------------------------------------------------------------------- /proto/atomone/dynamicfee/v1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.dynamicfee.v1; 3 | 4 | import "atomone/dynamicfee/v1/params.proto"; 5 | import "cosmos_proto/cosmos.proto"; 6 | import "cosmos/msg/v1/msg.proto"; 7 | import "gogoproto/gogo.proto"; 8 | import "amino/amino.proto"; 9 | 10 | option go_package = "github.com/atomone-hub/atomone/x/dynamicfee/types"; 11 | 12 | // Message service defines the types of messages supported by the dynamicfee 13 | // module. 14 | service Msg { 15 | option (cosmos.msg.v1.service) = true; 16 | 17 | // UpdateParams defines a method for updating the dynamicfee module parameters. 18 | rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); 19 | } 20 | 21 | // MsgUpdateParams defines the sdk.Msg/UpdateParams request type. It contains 22 | // the new parameters for the dynamicfee module. 23 | message MsgUpdateParams { 24 | option (cosmos.msg.v1.signer) = "authority"; 25 | option (amino.name) = "atomone/x/dynamicfee/v1/MsgUpdateParams"; 26 | 27 | // Authority defines the authority that is updating the dynamicfee module 28 | // parameters. 29 | string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 30 | // Params defines the new parameters for the dynamicfee module. 31 | Params params = 2 [ (gogoproto.nullable) = false ]; 32 | } 33 | 34 | // MsgUpdateParamsResponse defines the response structure for executing a 35 | // MsgUpdateParams message. 36 | message MsgUpdateParamsResponse {} 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/others.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Closes: #XXXX 4 | 5 | 7 | 8 | --- 9 | 10 | ### Author Checklist 11 | 12 | *All items are required. Please add a note to the item if the item is not applicable and 13 | please add links to any relevant follow up issues.* 14 | 15 | I have... 16 | 17 | - [ ] Included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title 18 | - [ ] Targeted the correct branch (see [PR Targeting](https://github.com/atomone-hub/atomone/blob/main/CONTRIBUTING.md#pr-targeting)) 19 | - [ ] Provided a link to the relevant issue or specification 20 | - [ ] Reviewed "Files changed" and left comments if necessary 21 | - [ ] Confirmed all CI checks have passed 22 | 23 | ### Reviewers Checklist 24 | 25 | *All items are required. Please add a note if the item is not applicable and please add 26 | your handle next to the items reviewed if you only reviewed selected items.* 27 | 28 | I have... 29 | 30 | - [ ] Confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title 31 | - [ ] Confirmed all author checklist items have been addressed 32 | - [ ] Confirmed that this PR does not change production code 33 | 34 | -------------------------------------------------------------------------------- /proto/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: cosmos 6 | repository: cosmos-proto 7 | commit: 04467658e59e44bbb22fe568206e1f70 8 | digest: shake256:73a640bd60e0c523b0f8237ff34eab67c45a38b64bbbde1d80224819d272dbf316ac183526bd245f994af6608b025f5130483d0133c5edd385531326b5990466 9 | - remote: buf.build 10 | owner: cosmos 11 | repository: cosmos-sdk 12 | commit: 5a6ab7bc14314acaa912d5e53aef1c2f 13 | digest: shake256:02c00c73493720055f9b57553a35b5550023a3c1914123b247956288a78fb913aff70e66552777ae14d759467e119079d484af081264a5dd607a94d9fbc8116b 14 | - remote: buf.build 15 | owner: cosmos 16 | repository: gogo-proto 17 | commit: 88ef6483f90f478fb938c37dde52ece3 18 | digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba 19 | - remote: buf.build 20 | owner: googleapis 21 | repository: googleapis 22 | commit: 61b203b9a9164be9a834f58c37be6f62 23 | digest: shake256:e619113001d6e284ee8a92b1561e5d4ea89a47b28bf0410815cb2fa23914df8be9f1a6a98dcf069f5bc2d829a2cfb1ac614863be45cd4f8a5ad8606c5f200224 24 | - remote: buf.build 25 | owner: protocolbuffers 26 | repository: wellknowntypes 27 | commit: 3ddd61d1f53d485abd3d3a2b47a62b8e 28 | digest: shake256:9e6799d56700d0470c3723a2fd027e8b4a41a07085a0c90c58e05f6c0038fac9b7a0170acd7692707a849983b1b8189aa33e7b73f91d68157f7136823115546b 29 | -------------------------------------------------------------------------------- /x/coredaos/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | 11 | "github.com/atomone-hub/atomone/x/coredaos/types" 12 | ) 13 | 14 | // GetQueryCmd returns the cli query commands for this module 15 | func GetQueryCmd() *cobra.Command { 16 | // Group coredaos queries under a subcommand 17 | cmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | 25 | cmd.AddCommand( 26 | GetQueryParamsCmd(), 27 | ) 28 | return cmd 29 | } 30 | 31 | func GetQueryParamsCmd() *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "params", 34 | Short: "shows the parameters of the module", 35 | Args: cobra.NoArgs, 36 | RunE: func(cmd *cobra.Command, args []string) error { 37 | clientCtx, err := client.GetClientQueryContext(cmd) 38 | if err != nil { 39 | return err 40 | } 41 | queryClient := types.NewQueryClient(clientCtx) 42 | res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) 43 | if err != nil { 44 | return err 45 | } 46 | return clientCtx.PrintProto(res) 47 | }, 48 | } 49 | flags.AddQueryFlagsToCmd(cmd) 50 | return cmd 51 | } 52 | -------------------------------------------------------------------------------- /tests/e2e/e2e_encode_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "encoding/base64" 5 | "path/filepath" 6 | 7 | "github.com/cosmos/cosmos-sdk/client" 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | const ( 12 | rawTxFile = "tx_raw.json" 13 | ) 14 | 15 | func (s *IntegrationTestSuite) testEncode() { 16 | chain := s.chainA 17 | _, encoded, err := buildRawTx(s.txConfig) 18 | s.Require().NoError(err) 19 | 20 | got := s.execEncode(chain, filepath.Join(atomoneHomePath, rawTxFile)) 21 | s.T().Logf("encoded tx: %s", got) 22 | s.Require().Equal(encoded, got) 23 | } 24 | 25 | func (s *IntegrationTestSuite) testDecode() { 26 | chain := s.chainA 27 | rawTx, encoded, err := buildRawTx(s.txConfig) 28 | s.Require().NoError(err) 29 | 30 | got := s.execDecode(chain, encoded) 31 | s.T().Logf("raw tx: %s", got) 32 | s.Require().Equal(string(rawTx), got) 33 | } 34 | 35 | // buildRawTx build a dummy tx using the TxBuilder and 36 | // return the JSON and encoded tx's 37 | func buildRawTx(txConfig client.TxConfig) ([]byte, string, error) { 38 | builder := txConfig.NewTxBuilder() 39 | builder.SetGasLimit(gas) 40 | builder.SetFeeAmount(sdk.NewCoins(standardFees)) 41 | builder.SetMemo("foomemo") 42 | tx, err := txConfig.TxJSONEncoder()(builder.GetTx()) 43 | if err != nil { 44 | return nil, "", err 45 | } 46 | txBytes, err := txConfig.TxEncoder()(builder.GetTx()) 47 | if err != nil { 48 | return nil, "", err 49 | } 50 | return tx, base64.StdEncoding.EncodeToString(txBytes), err 51 | } 52 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/docs.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Closes: #XXXX 4 | 5 | 7 | 8 | 9 | --- 10 | 11 | ### Author Checklist 12 | 13 | *All items are required. Please add a note to the item if the item is not applicable and 14 | please add links to any relevant follow up issues.* 15 | 16 | I have... 17 | 18 | - [ ] included the correct `docs:` prefix in the PR title 19 | - [ ] targeted the correct branch (see [PR Targeting](https://github.com/atomone-hub/atomone/blob/main/CONTRIBUTING.md#pr-targeting)) 20 | - [ ] provided a link to the relevant issue or specification 21 | - [ ] reviewed "Files changed" and left comments if necessary 22 | - [ ] confirmed all CI checks have passed 23 | 24 | ### Reviewers Checklist 25 | 26 | *All items are required. Please add a note if the item is not applicable and please add 27 | your handle next to the items reviewed if you only reviewed selected items.* 28 | 29 | I have... 30 | 31 | - [ ] Confirmed the correct `docs:` prefix in the PR title 32 | - [ ] Confirmed all author checklist items have been addressed 33 | - [ ] Confirmed that this PR only changes documentation 34 | - [ ] Reviewed content for consistency 35 | - [ ] Reviewed content for thoroughness 36 | - [ ] Reviewed content for spelling and grammar 37 | - [ ] Tested instructions (if applicable) 38 | 39 | -------------------------------------------------------------------------------- /contrib/scripts/test_localnet_liveness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CNT=0 4 | ITER=$1 5 | SLEEP=$2 6 | NUMBLOCKS=$3 7 | NODEADDR=$4 8 | 9 | if [ -z "$1" ]; then 10 | echo "Invalid argument: missing number of iterations" 11 | echo "sh test_localnet_liveness.sh " 12 | exit 1 13 | fi 14 | 15 | if [ -z "$2" ]; then 16 | echo "Invalid argument: missing sleep duration" 17 | echo "sh test_localnet_liveness.sh " 18 | exit 1 19 | fi 20 | 21 | if [ -z "$3" ]; then 22 | echo "Invalid argument: missing number of blocks" 23 | echo "sh test_localnet_liveness.sh " 24 | exit 1 25 | fi 26 | 27 | if [ -z "$4" ]; then 28 | echo "Invalid argument: missing node address" 29 | echo "sh test_localnet_liveness.sh " 30 | exit 1 31 | fi 32 | 33 | echo "running 'sh test_localnet_liveness.sh iterations=$ITER sleep=$SLEEP num-blocks=$NUMBLOCKS node-address=$NODEADDR'" 34 | 35 | while [ ${CNT} -lt $ITER ]; do 36 | curr_block=$(curl -s $NODEADDR:26657/status | jq -r '.result.sync_info.latest_block_height') 37 | 38 | tail liveness.out 39 | 40 | if [ ! -z ${curr_block} ]; then 41 | echo "Current block: ${curr_block}" 42 | fi 43 | 44 | if [ ! -z ${curr_block} ] && [ ${curr_block} -gt ${NUMBLOCKS} ]; then 45 | echo "Success: number of blocks reached" 46 | exit 0 47 | fi 48 | 49 | sleep $SLEEP 50 | done 51 | 52 | echo "Failed: timeout reached" 53 | exit 1 54 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/proposals_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | "github.com/atomone-hub/atomone/x/gov/types/v1beta1" 10 | ) 11 | 12 | func TestProposalStatus_Format(t *testing.T) { 13 | statusDepositPeriod, _ := v1beta1.ProposalStatusFromString("PROPOSAL_STATUS_DEPOSIT_PERIOD") 14 | tests := []struct { 15 | pt v1beta1.ProposalStatus 16 | sprintFArgs string 17 | expectedStringOutput string 18 | }{ 19 | {statusDepositPeriod, "%s", "PROPOSAL_STATUS_DEPOSIT_PERIOD"}, 20 | {statusDepositPeriod, "%v", "1"}, 21 | } 22 | for _, tt := range tests { 23 | got := fmt.Sprintf(tt.sprintFArgs, tt.pt) 24 | require.Equal(t, tt.expectedStringOutput, got) 25 | } 26 | } 27 | 28 | func TestContentFromProposalType(t *testing.T) { 29 | tests := []struct { 30 | proposalType string 31 | expectedType string 32 | }{ 33 | { 34 | proposalType: "TextProposal", 35 | expectedType: "", 36 | }, 37 | { 38 | proposalType: "text", 39 | expectedType: v1beta1.ProposalTypeText, 40 | }, 41 | { 42 | proposalType: "Text", 43 | expectedType: v1beta1.ProposalTypeText, 44 | }, 45 | } 46 | 47 | for _, test := range tests { 48 | content, ok := v1beta1.ContentFromProposalType("title", "foo", test.proposalType) 49 | if test.expectedType == "" { 50 | require.False(t, ok) 51 | continue 52 | } 53 | 54 | require.True(t, ok) 55 | require.NotNil(t, content) 56 | require.Equal(t, test.expectedType, content.ProposalType()) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /x/photon/simulation/genesis.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/cosmos/cosmos-sdk/types/module" 7 | 8 | "github.com/atomone-hub/atomone/x/photon/types" 9 | ) 10 | 11 | const ( 12 | MintDisabled = "mint_disabled" 13 | TxFeeExceptions = "tx_fee_exceptions" 14 | ) 15 | 16 | // GenMintDisabled returns a randomized MintDisabled param. 17 | func GenMintDisabled(r *rand.Rand) bool { 18 | return r.Int63n(101) <= 15 // 15% chance of mint being disabled 19 | } 20 | 21 | // GenTxFeeExceptions returns a wildcard to allow all transactions to use any 22 | // fee denom. 23 | // This is needed because other modules' simulations do not allow the fee coins 24 | // to be changed, so w/o this configuration all transactions would fail. 25 | func GenTxFeeExceptions(r *rand.Rand) []string { 26 | return []string{"*"} 27 | } 28 | 29 | // RandomizedGenState generates a random GenesisState for gov 30 | func RandomizedGenState(simState *module.SimulationState) { 31 | var mintDisabled bool 32 | simState.AppParams.GetOrGenerate( 33 | MintDisabled, &mintDisabled, simState.Rand, 34 | func(r *rand.Rand) { mintDisabled = GenMintDisabled(r) }, 35 | ) 36 | var txFeeExceptions []string 37 | simState.AppParams.GetOrGenerate( 38 | TxFeeExceptions, &txFeeExceptions, simState.Rand, 39 | func(r *rand.Rand) { txFeeExceptions = GenTxFeeExceptions(r) }, 40 | ) 41 | 42 | photonGenesis := types.NewGenesisState( 43 | types.NewParams(mintDisabled, txFeeExceptions), 44 | ) 45 | 46 | simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(photonGenesis) 47 | } 48 | -------------------------------------------------------------------------------- /proto/atomone/photon/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.photon.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "atomone/photon/v1/photon.proto"; 7 | import "cosmos_proto/cosmos.proto"; 8 | 9 | option go_package = "github.com/atomone-hub/atomone/x/photon/types"; 10 | 11 | // Query defines the gRPC querier service. 12 | service Query { 13 | // Parameters queries the parameters of the module. 14 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 15 | option (google.api.http).get = "/atomone/photon/v1/params"; 16 | } 17 | // ConversionRate queries the photon's conversion rate 18 | rpc ConversionRate(QueryConversionRateRequest) returns (QueryConversionRateResponse) { 19 | option (google.api.http).get = "/atomone/photon/v1/conversion_rate"; 20 | } 21 | } 22 | 23 | // QueryParamsRequest is request type for the Query/Params RPC method. 24 | message QueryParamsRequest {} 25 | 26 | // QueryParamsResponse is response type for the Query/Params RPC method. 27 | message QueryParamsResponse { 28 | // params holds all the parameters of this module. 29 | Params params = 1 [ (gogoproto.nullable) = false ]; 30 | } 31 | 32 | // QueryConversionRateRequest is request type for the Query/ConversionRate RPC method. 33 | message QueryConversionRateRequest {} 34 | 35 | // QueryConversionRateResponse is response type for the Query/ConversionRate RPC method. 36 | message QueryConversionRateResponse { 37 | // conversion_rate represents the factor used to convert atone to photon. 38 | string conversion_rate = 1 [ (cosmos_proto.scalar) = "cosmos.Dec" ]; 39 | } 40 | -------------------------------------------------------------------------------- /types/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | const codespace = "atomone" 8 | 9 | var ( 10 | // ErrTxDecode is returned if we cannot parse a transaction 11 | ErrTxDecode = errorsmod.Register(codespace, 1, "tx parse error") 12 | // ErrUnauthorized is used whenever a request without sufficient 13 | // authorization is handled. 14 | ErrUnauthorized = errorsmod.Register(codespace, 2, "unauthorized") 15 | 16 | // ErrInsufficientFunds is used when the account cannot pay requested amount. 17 | ErrInsufficientFunds = errorsmod.Register(codespace, 3, "insufficient funds") 18 | 19 | // ErrInsufficientFunds is used when the account cannot pay requested amount. 20 | ErrInsufficientFee = errorsmod.Register(codespace, 4, "insufficient fee") 21 | 22 | // ErrInvalidCoins is used when sdk.Coins are invalid. 23 | ErrInvalidCoins = errorsmod.Register(codespace, 5, "invalid coins") 24 | 25 | // ErrInvalidType defines an error an invalid type. 26 | ErrInvalidType = errorsmod.Register(codespace, 6, "invalid type") 27 | 28 | // ErrLogic defines an internal logic error, e.g. an invariant or assertion 29 | // that is violated. It is a programmer error, not a user-facing error. 30 | ErrLogic = errorsmod.Register(codespace, 7, "internal logic error") 31 | 32 | // ErrNotFound defines an error when requested entity doesn't exist in the state. 33 | ErrNotFound = errorsmod.Register(codespace, 8, "not found") 34 | 35 | // ErrInsufficientStake is used when the account has insufficient staked tokens. 36 | ErrInsufficientStake = errorsmod.Register(codespace, 9, "insufficient stake") 37 | ) 38 | -------------------------------------------------------------------------------- /.github/workflows/docker-push.yml: -------------------------------------------------------------------------------- 1 | # source: https://docs.github.com/en/enterprise-cloud@latest/actions/publishing-packages/publishing-docker-images 2 | name: Create and publish a Docker image 3 | 4 | on: 5 | push: 6 | branches: ['release'] 7 | 8 | env: 9 | REGISTRY: ghcr.io 10 | IMAGE_NAME: ${{ github.repository }} 11 | 12 | jobs: 13 | build-and-push-image: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: read 17 | packages: write 18 | 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | 23 | - name: Log in to the Container registry 24 | uses: docker/login-action@v3.0.0 25 | with: 26 | registry: ${{ env.REGISTRY }} 27 | username: ${{ github.actor }} 28 | password: ${{ secrets.GITHUB_TOKEN }} 29 | 30 | - name: Extract metadata (tags, labels) for Docker 31 | id: meta 32 | uses: docker/metadata-action@v5.5.1 33 | with: 34 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 35 | 36 | - name: Build and push Docker image 37 | uses: docker/build-push-action@v5.1.0 38 | with: 39 | context: . 40 | push: true 41 | tags: ${{ steps.meta.outputs.tags }} 42 | labels: ${{ steps.meta.outputs.labels }} 43 | 44 | - name: Build and push e2e docker image 45 | uses: docker/build-push-action@v5.1.0 46 | with: 47 | context: . 48 | file: Dockerfile.e2e 49 | push: true 50 | tags: ${{ steps.meta.outputs.tags }}-e2e 51 | labels: ${{ steps.meta.outputs.labels }} 52 | -------------------------------------------------------------------------------- /cmd/atomoned/cmd/bech32_convert.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | appparams "github.com/atomone-hub/atomone/app/params" 9 | addressutil "github.com/atomone-hub/atomone/pkg/address" 10 | ) 11 | 12 | var flagBech32Prefix = "prefix" 13 | 14 | // AddBech32ConvertCommand returns bech32-convert cobra Command. 15 | func AddBech32ConvertCommand() *cobra.Command { 16 | cmd := &cobra.Command{ 17 | Use: "bech32-convert [address]", 18 | Short: "Convert any bech32 string to the cosmos prefix", 19 | Long: `Convert any bech32 string to the cosmos prefix 20 | 21 | Example: 22 | atomoned debug bech32-convert akash1a6zlyvpnksx8wr6wz8wemur2xe8zyh0ytz6d88 23 | 24 | atomoned debug bech32-convert stride1673f0t8p893rqyqe420mgwwz92ac4qv6synvx2 --prefix osmo 25 | `, 26 | Args: cobra.ExactArgs(1), 27 | RunE: func(cmd *cobra.Command, args []string) error { 28 | bech32prefix, err := cmd.Flags().GetString(flagBech32Prefix) 29 | if err != nil { 30 | return err 31 | } 32 | 33 | address := args[0] 34 | convertedAddress, err := addressutil.ConvertBech32Prefix(address, bech32prefix) 35 | if err != nil { 36 | return fmt.Errorf("convertation failed: %s", err) 37 | } 38 | 39 | cmd.Println(convertedAddress) 40 | 41 | return nil 42 | }, 43 | } 44 | 45 | cmd.Flags().StringP(flagBech32Prefix, "p", appparams.Bech32PrefixAccAddr, "Bech32 Prefix to encode to") 46 | 47 | return cmd 48 | } 49 | 50 | // addDebugCommands injects custom debug commands into another command as children. 51 | func addDebugCommands(cmd *cobra.Command) *cobra.Command { 52 | cmd.AddCommand(AddBech32ConvertCommand()) 53 | return cmd 54 | } 55 | -------------------------------------------------------------------------------- /x/dynamicfee/fuzz/tx_priority_test.go: -------------------------------------------------------------------------------- 1 | package fuzz_test 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | 7 | sdkmath "cosmossdk.io/math" 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | "github.com/stretchr/testify/require" 10 | "pgregory.net/rapid" 11 | 12 | "github.com/atomone-hub/atomone/x/dynamicfee/ante" 13 | ) 14 | 15 | type input struct { 16 | payFee sdk.Coin 17 | gasLimit int64 18 | currentGasPrice sdk.DecCoin 19 | } 20 | 21 | // TestGetTxPriority ensures that tx priority is properly bounded 22 | func TestGetTxPriority(t *testing.T) { 23 | rapid.Check(t, func(t *rapid.T) { 24 | inputs := createRandomInput(t) 25 | 26 | priority := ante.GetTxPriority(inputs.payFee, inputs.gasLimit, inputs.currentGasPrice) 27 | require.GreaterOrEqual(t, priority, int64(0)) 28 | require.LessOrEqual(t, priority, int64(math.MaxInt64)) 29 | }) 30 | } 31 | 32 | // CreateRandomInput returns a random inputs to the priority function. 33 | func createRandomInput(t *rapid.T) input { 34 | denom := "skip" 35 | 36 | price := rapid.Int64Range(1, 1_000_000_000).Draw(t, "gas price") 37 | priceDec := sdkmath.LegacyNewDecWithPrec(price, 6) 38 | 39 | gasLimit := rapid.Int64Range(1_000_000, 1_000_000_000_000).Draw(t, "gas limit") 40 | 41 | if priceDec.MulInt64(gasLimit).GTE(sdkmath.LegacyNewDec(math.MaxInt64)) { 42 | t.Fatalf("not supposed to happen") 43 | } 44 | 45 | payFeeAmt := rapid.Int64Range(priceDec.MulInt64(gasLimit).TruncateInt64(), math.MaxInt64).Draw(t, "fee amount") 46 | 47 | return input{ 48 | payFee: sdk.NewCoin(denom, sdkmath.NewInt(payFeeAmt)), 49 | gasLimit: gasLimit, 50 | currentGasPrice: sdk.NewDecCoinFromDec(denom, priceDec), 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Create a proposal to request a feature 4 | labels: enhancement, epic, needs-triage 5 | --- 6 | 7 | 13 | 14 | ## Summary 15 | 16 | 17 | 18 | ## Problem Definition 19 | 20 | 24 | 25 | ## Proposal 26 | 27 | 28 | 29 | ## Task list 30 | 31 | ```[tasklist] 32 | ### Must have 33 | - [ ] discuss proposal (if proposal rejected, close EPIC) 34 | - [ ] create ADR (if ADR rejected, close EPIC) 35 | - [ ] add sub-tasks needed to implement the proposed feature 36 | ``` 37 | 38 | ```[tasklist] 39 | ### Nice to have 40 | - [ ] add sub-tasks that are nice to have for the proposed feature 41 | ``` 42 | ____ 43 | 44 | #### For Admin Use 45 | 46 | - [ ] Not duplicate issue 47 | - [ ] Appropriate labels applied 48 | - [ ] Appropriate contributors tagged 49 | - [ ] Contributor assigned/self-assigned 50 | - [ ] Is a spike necessary to map out how the issue should be approached? 51 | -------------------------------------------------------------------------------- /proto/atomone/gov/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package atomone.gov.v1beta1; 4 | 5 | import "gogoproto/gogo.proto"; 6 | import "atomone/gov/v1beta1/gov.proto"; 7 | import "amino/amino.proto"; 8 | 9 | option go_package = "github.com/atomone-hub/atomone/x/gov/types/v1beta1"; 10 | 11 | // GenesisState defines the gov module's genesis state. 12 | message GenesisState { 13 | // starting_proposal_id is the ID of the starting proposal. 14 | uint64 starting_proposal_id = 1; 15 | // deposits defines all the deposits present at genesis. 16 | repeated Deposit deposits = 2 [ 17 | (gogoproto.castrepeated) = "Deposits", 18 | (gogoproto.nullable) = false, 19 | (amino.dont_omitempty) = true 20 | ]; 21 | // votes defines all the votes present at genesis. 22 | repeated Vote votes = 3 [ 23 | (gogoproto.castrepeated) = "Votes", 24 | (gogoproto.nullable) = false, 25 | (amino.dont_omitempty) = true 26 | ]; 27 | // proposals defines all the proposals present at genesis. 28 | repeated Proposal proposals = 4 [ 29 | (gogoproto.castrepeated) = "Proposals", 30 | (gogoproto.nullable) = false, 31 | (amino.dont_omitempty) = true 32 | ]; 33 | // params defines all the parameters of related to deposit. 34 | DepositParams deposit_params = 5 35 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 36 | // params defines all the parameters of related to voting. 37 | VotingParams voting_params = 6 38 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 39 | // params defines all the parameters of related to tally. 40 | TallyParams tally_params = 7 41 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 42 | } 43 | -------------------------------------------------------------------------------- /x/photon/types/msgs_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "cosmossdk.io/math" 7 | "github.com/stretchr/testify/require" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 11 | 12 | appparams "github.com/atomone-hub/atomone/app/params" 13 | ) 14 | 15 | func TestMsgMintPhoton_ValidateBasic(t *testing.T) { 16 | tests := []struct { 17 | name string 18 | msg MsgMintPhoton 19 | err error 20 | }{ 21 | { 22 | name: "fail: invalid toAddress", 23 | msg: MsgMintPhoton{ 24 | ToAddress: "invalid_address", 25 | }, 26 | err: sdkerrors.ErrInvalidAddress, 27 | }, 28 | { 29 | name: "fail: negative amount", 30 | msg: MsgMintPhoton{ 31 | ToAddress: sdk.AccAddress("test1").String(), 32 | Amount: sdk.Coin{ 33 | Denom: appparams.BondDenom, 34 | Amount: math.NewInt(-1), 35 | }, 36 | }, 37 | err: sdkerrors.ErrInvalidCoins, 38 | }, 39 | { 40 | name: "fail: not positive amount", 41 | msg: MsgMintPhoton{ 42 | ToAddress: sdk.AccAddress("test1").String(), 43 | Amount: sdk.Coin{ 44 | Denom: appparams.BondDenom, 45 | Amount: math.NewInt(0), 46 | }, 47 | }, 48 | err: sdkerrors.ErrInvalidCoins, 49 | }, 50 | { 51 | name: "ok", 52 | msg: MsgMintPhoton{ 53 | ToAddress: sdk.AccAddress("test1").String(), 54 | Amount: sdk.NewInt64Coin(appparams.BondDenom, 1), 55 | }, 56 | }, 57 | } 58 | for _, tt := range tests { 59 | t.Run(tt.name, func(t *testing.T) { 60 | err := tt.msg.ValidateBasic() 61 | if tt.err != nil { 62 | require.ErrorIs(t, err, tt.err) 63 | return 64 | } 65 | require.NoError(t, err) 66 | }) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /x/dynamicfee/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 10 | ) 11 | 12 | var _ types.MsgServer = (*MsgServer)(nil) 13 | 14 | // MsgServer is the server API for x/dynamicfee Msg service. 15 | type MsgServer struct { 16 | k *Keeper 17 | } 18 | 19 | // NewMsgServer returns the MsgServer implementation. 20 | func NewMsgServer(k *Keeper) types.MsgServer { 21 | return &MsgServer{k} 22 | } 23 | 24 | // Params defines a method that updates the module's parameters. The signer of the message must 25 | // be the module authority. 26 | func (ms MsgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { 27 | ctx := sdk.UnwrapSDKContext(goCtx) 28 | 29 | if msg.Authority != ms.k.GetAuthority() { 30 | return nil, fmt.Errorf("invalid authority to execute message") 31 | } 32 | 33 | gotParams, err := ms.k.GetParams(ctx) 34 | if err != nil { 35 | return nil, fmt.Errorf("error getting params: %w", err) 36 | } 37 | 38 | // if going from disabled -> enabled, set enabled height 39 | if !gotParams.Enabled && msg.Params.Enabled { 40 | ms.k.SetEnabledHeight(ctx, ctx.BlockHeight()) 41 | } 42 | 43 | params := msg.Params 44 | if err := ms.k.SetParams(ctx, params); err != nil { 45 | return nil, fmt.Errorf("error setting params: %w", err) 46 | } 47 | 48 | newState := types.NewState(params.Window, params.MinBaseGasPrice, params.MinLearningRate) 49 | if err := ms.k.SetState(ctx, newState); err != nil { 50 | return nil, fmt.Errorf("error setting state: %w", err) 51 | } 52 | 53 | return &types.MsgUpdateParamsResponse{}, nil 54 | } 55 | -------------------------------------------------------------------------------- /client/docs/swagger-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /x/coredaos/keeper/keeper.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "cosmossdk.io/collections" 5 | "cosmossdk.io/core/store" 6 | "cosmossdk.io/log" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | "github.com/atomone-hub/atomone/x/coredaos/types" 12 | ) 13 | 14 | type Keeper struct { 15 | cdc codec.BinaryCodec 16 | storeService store.KVStoreService 17 | authority string 18 | 19 | govKeeper types.GovKeeper 20 | stakingKeeper types.StakingKeeper 21 | 22 | Schema collections.Schema 23 | Params collections.Item[types.Params] 24 | } 25 | 26 | func NewKeeper( 27 | cdc codec.BinaryCodec, 28 | storeService store.KVStoreService, 29 | authority string, 30 | govKeeper types.GovKeeper, 31 | stakingKeeper types.StakingKeeper, 32 | ) *Keeper { 33 | if _, err := sdk.AccAddressFromBech32(authority); err != nil { 34 | panic(err) 35 | } 36 | 37 | sb := collections.NewSchemaBuilder(storeService) 38 | k := &Keeper{ 39 | cdc: cdc, 40 | storeService: storeService, 41 | authority: authority, 42 | govKeeper: govKeeper, 43 | stakingKeeper: stakingKeeper, 44 | Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), 45 | } 46 | 47 | schema, err := sb.Build() 48 | if err != nil { 49 | panic(err) 50 | } 51 | k.Schema = schema 52 | return k 53 | } 54 | 55 | // Logger returns a coredaos module-specific logger. 56 | func (k Keeper) Logger(ctx sdk.Context) log.Logger { 57 | return ctx.Logger().With("module", "x/"+types.ModuleName) 58 | } 59 | 60 | // GetAuthority returns the address that is capable of executing a MsgUpdateParams message. 61 | func (k Keeper) GetAuthority() string { 62 | return k.authority 63 | } 64 | -------------------------------------------------------------------------------- /tests/e2e/e2e_evidence_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "cosmossdk.io/x/evidence/exported" 9 | evidencetypes "cosmossdk.io/x/evidence/types" 10 | ) 11 | 12 | func (s *IntegrationTestSuite) testEvidenceQueries() { 13 | s.Run("queries", func() { 14 | var ( 15 | valIdx = 0 16 | chain = s.chainA 17 | chainAPI = fmt.Sprintf("http://%s", s.valResources[chain.id][valIdx].GetHostPort("1317/tcp")) 18 | ) 19 | res, err := s.queryAllEvidence(chainAPI) 20 | s.Require().NoError(err) 21 | s.Require().Equal(numberOfEvidences, len(res.Evidence)) 22 | for _, evidence := range res.Evidence { 23 | var exportedEvidence exported.Evidence 24 | err := s.cdc.UnpackAny(evidence, &exportedEvidence) 25 | s.Require().NoError(err) 26 | eq, ok := exportedEvidence.(*evidencetypes.Equivocation) 27 | s.Require().True(ok) 28 | s.execQueryEvidence(chain, valIdx, string(eq.Hash())) // TODO: check this string conversion was good 29 | } 30 | }) 31 | } 32 | 33 | func (s *IntegrationTestSuite) execQueryEvidence(c *chain, valIdx int, hash string) (res evidencetypes.Equivocation) { 34 | ctx, cancel := context.WithTimeout(context.Background(), time.Minute) 35 | defer cancel() 36 | 37 | s.T().Logf("querying evidence %X on chain %s", hash, c.id) 38 | 39 | atomoneCommand := []string{ 40 | atomonedBinary, 41 | queryCommand, 42 | evidencetypes.ModuleName, 43 | hash, 44 | } 45 | 46 | s.executeAtomoneTxCommand(ctx, c, atomoneCommand, valIdx, func(stdOut []byte, stdErr []byte) error { 47 | // TODO parse evidence after fix the SDK 48 | // https://github.com/cosmos/cosmos-sdk/issues/13444 49 | // s.Require().NoError(yaml.Unmarshal(stdOut, &res)) 50 | return nil 51 | }) 52 | return res 53 | } 54 | -------------------------------------------------------------------------------- /x/photon/ante/expected_keepers_mocks_test.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: x/photon/ante/expected_keepers.go 3 | 4 | // Package ante_test is a generated GoMock package. 5 | package ante_test 6 | 7 | import ( 8 | reflect "reflect" 9 | 10 | types "github.com/atomone-hub/atomone/x/photon/types" 11 | types0 "github.com/cosmos/cosmos-sdk/types" 12 | gomock "github.com/golang/mock/gomock" 13 | ) 14 | 15 | // MockPhotonKeeper is a mock of PhotonKeeper interface. 16 | type MockPhotonKeeper struct { 17 | ctrl *gomock.Controller 18 | recorder *MockPhotonKeeperMockRecorder 19 | } 20 | 21 | // MockPhotonKeeperMockRecorder is the mock recorder for MockPhotonKeeper. 22 | type MockPhotonKeeperMockRecorder struct { 23 | mock *MockPhotonKeeper 24 | } 25 | 26 | // NewMockPhotonKeeper creates a new mock instance. 27 | func NewMockPhotonKeeper(ctrl *gomock.Controller) *MockPhotonKeeper { 28 | mock := &MockPhotonKeeper{ctrl: ctrl} 29 | mock.recorder = &MockPhotonKeeperMockRecorder{mock} 30 | return mock 31 | } 32 | 33 | // EXPECT returns an object that allows the caller to indicate expected use. 34 | func (m *MockPhotonKeeper) EXPECT() *MockPhotonKeeperMockRecorder { 35 | return m.recorder 36 | } 37 | 38 | // GetParams mocks base method. 39 | func (m *MockPhotonKeeper) GetParams(ctx types0.Context) types.Params { 40 | m.ctrl.T.Helper() 41 | ret := m.ctrl.Call(m, "GetParams", ctx) 42 | ret0, _ := ret[0].(types.Params) 43 | return ret0 44 | } 45 | 46 | // GetParams indicates an expected call of GetParams. 47 | func (mr *MockPhotonKeeperMockRecorder) GetParams(ctx interface{}) *gomock.Call { 48 | mr.mock.ctrl.T.Helper() 49 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParams", reflect.TypeOf((*MockPhotonKeeper)(nil).GetParams), ctx) 50 | } 51 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 10 5 | 6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 8 | daysUntilClose: 4 9 | 10 | # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) 11 | onlyLabels: [] 12 | 13 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 14 | exemptLabels: 15 | - blocked 16 | - pinned 17 | - security 18 | 19 | # Set to true to ignore issues in a project (defaults to false) 20 | exemptProjects: true 21 | 22 | # Set to true to ignore issues in a milestone (defaults to false) 23 | exemptMilestones: true 24 | 25 | # Label to use when marking as stale 26 | staleLabel: stale 27 | 28 | # Comment to post when marking as stale. Set to `false` to disable 29 | markComment: > 30 | This issue has been automatically marked as stale because it has not had 31 | recent activity. It will be closed if no further activity occurs. Thank you 32 | for your contributions. 33 | # Limit the number of actions per hour, from 1-30. Default is 30 34 | limitPerRun: 30 35 | 36 | # Limit to only `issues` or `pulls` 37 | only: pulls 38 | 39 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': 40 | pulls: 41 | daysUntilStale: 30 42 | markComment: > 43 | This pull request has been automatically marked as stale because it has not had 44 | recent activity. It will be closed if no further activity occurs. Thank you 45 | for your contributions. 46 | -------------------------------------------------------------------------------- /x/gov/types/v1/min_deposit.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "cosmossdk.io/math" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | func GetNewMinDeposit(minDepositFloor, lastMinDeposit sdk.Coins, percChange math.LegacyDec) sdk.Coins { 10 | newMinDeposit := sdk.Coins{} 11 | minDepositFloorDenomsSeen := make(map[string]bool) 12 | for _, lastMinDepositCoin := range lastMinDeposit { 13 | minDepositFloorCoinAmt := minDepositFloor.AmountOf(lastMinDepositCoin.Denom) 14 | if minDepositFloorCoinAmt.IsZero() { 15 | // minDepositFloor was changed since last update, 16 | // and this coin was removed. 17 | // reflect this also in the current min initial deposit, 18 | // i.e. remove this coin 19 | continue 20 | } 21 | minDepositFloorDenomsSeen[lastMinDepositCoin.Denom] = true 22 | minDepositCoinAmt := lastMinDepositCoin.Amount.ToLegacyDec().Mul(percChange).TruncateInt() 23 | if minDepositCoinAmt.LT(minDepositFloorCoinAmt) { 24 | newMinDeposit = append(newMinDeposit, sdk.NewCoin(lastMinDepositCoin.Denom, minDepositFloorCoinAmt)) 25 | } else { 26 | newMinDeposit = append(newMinDeposit, sdk.NewCoin(lastMinDepositCoin.Denom, minDepositCoinAmt)) 27 | } 28 | } 29 | 30 | // make sure any new denoms in minDepositFloor are added to minDeposit 31 | for _, minDepositFloorCoin := range minDepositFloor { 32 | if _, seen := minDepositFloorDenomsSeen[minDepositFloorCoin.Denom]; !seen { 33 | minDepositCoinAmt := minDepositFloorCoin.Amount.ToLegacyDec().Mul(percChange).TruncateInt() 34 | if minDepositCoinAmt.LT(minDepositFloorCoin.Amount) { 35 | newMinDeposit = append(newMinDeposit, minDepositFloorCoin) 36 | } else { 37 | newMinDeposit = append(newMinDeposit, sdk.NewCoin(minDepositFloorCoin.Denom, minDepositCoinAmt)) 38 | } 39 | } 40 | } 41 | 42 | return newMinDeposit 43 | } 44 | -------------------------------------------------------------------------------- /app/upgrades/types.go: -------------------------------------------------------------------------------- 1 | package upgrades 2 | 3 | import ( 4 | store "cosmossdk.io/store/types" 5 | upgradetypes "cosmossdk.io/x/upgrade/types" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/module" 9 | 10 | "github.com/atomone-hub/atomone/app/keepers" 11 | ) 12 | 13 | // Upgrade defines a struct containing necessary fields that a SoftwareUpgradeProposal 14 | // must have written, in order for the state migration to go smoothly. 15 | // An upgrade must implement this struct, and then set it in the app.go. 16 | // The app.go will then define the handler. 17 | type Upgrade struct { 18 | // Upgrade version name, for the upgrade handler, e.g. `v7` 19 | UpgradeName string 20 | 21 | // CreateUpgradeHandler defines the function that creates an upgrade handler 22 | CreateUpgradeHandler func(*module.Manager, module.Configurator, *keepers.AppKeepers) upgradetypes.UpgradeHandler 23 | 24 | // Store upgrades, should be used for any new modules introduced, new modules deleted, or store names renamed. 25 | StoreUpgrades store.StoreUpgrades 26 | } 27 | 28 | // Fork defines a struct containing the requisite fields for a non-software upgrade proposal 29 | // Hard Fork at a given height to implement. 30 | // There is one time code that can be added for the start of the Fork, in `BeginForkLogic`. 31 | // Any other change in the code should be height-gated, if the goal is to have old and new binaries 32 | // to be compatible prior to the upgrade height. 33 | type Fork struct { 34 | // Upgrade version name, for the upgrade handler, e.g. `v7` 35 | UpgradeName string 36 | // height the upgrade occurs at 37 | UpgradeHeight int64 38 | 39 | // Function that runs some custom state transition code at the beginning of a fork. 40 | BeginForkLogic func(ctx sdk.Context, keepers *keepers.AppKeepers) 41 | } 42 | -------------------------------------------------------------------------------- /x/photon/types/msgs.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | 9 | "github.com/atomone-hub/atomone/app/params" 10 | "github.com/atomone-hub/atomone/x/gov/types" 11 | ) 12 | 13 | var _, _ sdk.Msg = &MsgMintPhoton{}, &MsgUpdateParams{} 14 | 15 | func NewMsgMintPhoton(toAddr sdk.AccAddress, amount sdk.Coin) *MsgMintPhoton { 16 | return &MsgMintPhoton{ 17 | ToAddress: toAddr.String(), 18 | Amount: amount, 19 | } 20 | } 21 | 22 | func (msg *MsgMintPhoton) ValidateBasic() error { 23 | if _, err := sdk.AccAddressFromBech32(msg.ToAddress); err != nil { 24 | return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid toAddress: %s", err) 25 | } 26 | if err := msg.Amount.Validate(); err != nil { 27 | return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "invalid coin to burn: %s", err) 28 | } 29 | if !msg.Amount.IsPositive() { 30 | return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "coin to burn must be positive") 31 | } 32 | // Ensure burned amount denom is bond denom 33 | if msg.Amount.Denom != params.BondDenom { 34 | return errorsmod.Wrapf(ErrBurnInvalidDenom, "invalid denom %s", msg.Amount.Denom) 35 | } 36 | return nil 37 | } 38 | 39 | // Route implements the sdk.Msg interface. 40 | func (msg MsgUpdateParams) Route() string { return types.RouterKey } 41 | 42 | // Type implements the sdk.Msg interface. 43 | func (msg MsgUpdateParams) Type() string { return sdk.MsgTypeURL(&msg) } 44 | 45 | // ValidateBasic implements the sdk.Msg interface. 46 | func (msg MsgUpdateParams) ValidateBasic() error { 47 | if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { 48 | return sdkerrors.ErrInvalidAddress.Wrapf("invalid authority address: %s", err) 49 | } 50 | 51 | return msg.Params.ValidateBasic() 52 | } 53 | -------------------------------------------------------------------------------- /proto/atomone/dynamicfee/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.dynamicfee.v1; 3 | 4 | option go_package = "github.com/atomone-hub/atomone/x/dynamicfee/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos_proto/cosmos.proto"; 8 | import "atomone/dynamicfee/v1/params.proto"; 9 | 10 | // GenesisState defines the dynamicfee module's genesis state. 11 | message GenesisState { 12 | // Params are the parameters for the dynamicfee module. These parameters 13 | // can be utilized to implement both the base EIP-1559 dynamic fee pricing 14 | // and the AIMD EIP-1559 dynamic fee pricing. 15 | Params params = 1 [ (gogoproto.nullable) = false ]; 16 | 17 | // State contains the current state of the AIMD dynamic fee pricer. 18 | State state = 2 [ (gogoproto.nullable) = false ]; 19 | } 20 | 21 | // State is utilized to track the current state of the dynamic fee pricer. 22 | // This includes the current base fee, learning rate, and block gas within the 23 | // specified AIMD window. 24 | message State { 25 | // BaseGasPrice is the current base fee. This is denominated in the fee per 26 | // gas unit. 27 | string base_gas_price = 1 [ 28 | (cosmos_proto.scalar) = "cosmos.Dec", 29 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 30 | (gogoproto.nullable) = false 31 | ]; 32 | 33 | // LearningRate is the current learning rate. 34 | string learning_rate = 2 [ 35 | (cosmos_proto.scalar) = "cosmos.Dec", 36 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 37 | (gogoproto.nullable) = false 38 | ]; 39 | 40 | // Window contains a list of the last blocks' gas values. This is used 41 | // to calculate the next base fee. This stores the number of units of gas 42 | // consumed per block. 43 | repeated uint64 window = 3; 44 | 45 | // Index is the index of the current block in the block gas window. 46 | uint64 index = 4; 47 | } 48 | -------------------------------------------------------------------------------- /x/coredaos/testutil/keeper.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/golang/mock/gomock" 7 | 8 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 | tmtime "github.com/cometbft/cometbft/types/time" 10 | 11 | storetypes "cosmossdk.io/store/types" 12 | 13 | "github.com/cosmos/cosmos-sdk/runtime" 14 | "github.com/cosmos/cosmos-sdk/testutil" 15 | sdk "github.com/cosmos/cosmos-sdk/types" 16 | moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 17 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 18 | 19 | "github.com/atomone-hub/atomone/x/coredaos/keeper" 20 | "github.com/atomone-hub/atomone/x/coredaos/types" 21 | govtypes "github.com/atomone-hub/atomone/x/gov/types" 22 | ) 23 | 24 | type Mocks struct { 25 | GovKeeper *MockGovKeeper 26 | StakingKeeper *MockStakingKeeper 27 | } 28 | 29 | func SetupMsgServer(t *testing.T) (types.MsgServer, *keeper.Keeper, Mocks, sdk.Context) { 30 | t.Helper() 31 | k, m, ctx := SetupCoredaosKeeper(t) 32 | return keeper.NewMsgServer(k), k, m, ctx 33 | } 34 | 35 | func SetupCoredaosKeeper(t *testing.T) ( 36 | *keeper.Keeper, 37 | Mocks, 38 | sdk.Context, 39 | ) { 40 | t.Helper() 41 | ctrl := gomock.NewController(t) 42 | m := Mocks{ 43 | GovKeeper: NewMockGovKeeper(ctrl), 44 | StakingKeeper: NewMockStakingKeeper(ctrl), 45 | } 46 | 47 | key := storetypes.NewKVStoreKey(types.StoreKey) 48 | storeService := runtime.NewKVStoreService(key) 49 | testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) 50 | ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()}) 51 | encCfg := moduletestutil.MakeTestEncodingConfig() 52 | types.RegisterInterfaces(encCfg.InterfaceRegistry) 53 | authority := authtypes.NewModuleAddress(govtypes.ModuleName).String() 54 | return keeper.NewKeeper(encCfg.Codec, storeService, authority, m.GovKeeper, m.StakingKeeper), m, ctx 55 | } 56 | -------------------------------------------------------------------------------- /contrib/generate_release_note/main.go: -------------------------------------------------------------------------------- 1 | //go:build exclude 2 | // +build exclude 3 | 4 | package main 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | "os" 10 | "strings" 11 | ) 12 | 13 | func main() { 14 | args := os.Args 15 | if len(args) != 4 { 16 | fmt.Println("please add os.Args release version, build_report path and CHANGELOG.md path, example: go run main.go v7.0.0 ../../artifacts/build_report ../../CHANGELOG.md") 17 | } 18 | 19 | buildReportPath := args[2] 20 | changelogPath := args[3] 21 | 22 | buildReport, err := os.ReadFile(buildReportPath) 23 | if err != nil { 24 | fmt.Printf("file error: %s\n", err) 25 | } 26 | 27 | changelog, err := FindChangelog(changelogPath, args[1]) 28 | if err != nil { 29 | fmt.Printf("cannot find changelog: %s\n", err) 30 | } 31 | 32 | note := strings.Builder{} 33 | note.WriteString(fmt.Sprintf("# AtomOne %s Release Notes\n", args[1])) 34 | note.WriteString(changelog) 35 | note.WriteString("```\n") 36 | note.Write(buildReport) 37 | note.WriteString("```\n") 38 | 39 | f, err := os.Create("./releasenote") 40 | if err != nil { 41 | fmt.Printf("cannot create a release note: %s\n", err) 42 | } 43 | defer f.Close() 44 | 45 | _, err = f.WriteString(note.String()) 46 | if err != nil { 47 | fmt.Printf("cannot write to releasenote: %s\n", err) 48 | } 49 | } 50 | 51 | func FindChangelog(file, version string) (string, error) { 52 | data, err := os.ReadFile(file) 53 | if err != nil { 54 | return "", errors.New("read changelog file failed") 55 | } 56 | 57 | changelogs := string(data) 58 | i := strings.Index(changelogs, "["+version) 59 | if i == -1 { 60 | // -1 means not found 61 | return "", fmt.Errorf("cannot find version %s", version) 62 | } 63 | j := strings.Index(changelogs[i:], "##") 64 | if j == -1 { 65 | // -1 means not found 66 | return "", fmt.Errorf("cannot find the end of %s's changelog", version) 67 | } 68 | 69 | return changelogs[i : i+j], nil 70 | } 71 | -------------------------------------------------------------------------------- /docs/architecture/adr-template.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # ADR {ADR-NUMBER}: {TITLE} 6 | 7 | ## Changelog 8 | 9 | - {date}: {changelog} 10 | 11 | ## Status 12 | 13 | {DRAFT | PROPOSED} Not Implemented 14 | 15 | > Please have a look at the [PROCESS](./PROCESS.md#adr-status) page. 16 | > Use DRAFT if the ADR is in a draft stage (draft PR) or PROPOSED if it's in review. 17 | 18 | ## Abstract 19 | 20 | > "If you can't explain it simply, you don't understand it well enough." Provide 21 | > a simplified and layman-accessible explanation of the ADR. 22 | > A short (~200 word) description of the issue being addressed. 23 | 24 | ## Context 25 | 26 | > This section contains all the context one needs to understand the current state, and why there is a problem. 27 | > It should be as succinct as possible and introduce the high level idea behind the solution. 28 | > The language in this section is value-neutral. It is simply describing facts. 29 | 30 | ## Decision 31 | 32 | > This section explains all of the details of the proposed solution, including implementation details. 33 | It should also describe affects / corollary items that may need to be changed as a part of this. 34 | If the proposed change will be large, please also indicate a way to do the change to maximize ease of review. 35 | (e.g. the optimal split of things to do between separate PR's) 36 | 37 | ## Consequences 38 | 39 | > This section describes the consequences, after applying the decision. 40 | > All consequences should be summarized here, not just the "positive" ones. 41 | 42 | ### Positive 43 | 44 | > {positive consequences} 45 | 46 | ### Negative 47 | 48 | > {negative consequences} 49 | 50 | ### Neutral 51 | 52 | > {neutral consequences} 53 | 54 | ## References 55 | 56 | > Are there any relevant PR comments, issues that led up to this, or articles referrenced for why we made the given design choice? If so link them here! 57 | 58 | * {reference link} 59 | -------------------------------------------------------------------------------- /x/photon/testutil/keeper.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/golang/mock/gomock" 7 | 8 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 | tmtime "github.com/cometbft/cometbft/types/time" 10 | 11 | storetypes "cosmossdk.io/store/types" 12 | 13 | "github.com/cosmos/cosmos-sdk/testutil" 14 | sdk "github.com/cosmos/cosmos-sdk/types" 15 | moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 16 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 17 | 18 | govtypes "github.com/atomone-hub/atomone/x/gov/types" 19 | "github.com/atomone-hub/atomone/x/photon/keeper" 20 | "github.com/atomone-hub/atomone/x/photon/types" 21 | ) 22 | 23 | type Mocks struct { 24 | AccountKeeper *MockAccountKeeper 25 | BankKeeper *MockBankKeeper 26 | StakingKeeper *MockStakingKeeper 27 | } 28 | 29 | func SetupMsgServer(t *testing.T) (types.MsgServer, *keeper.Keeper, Mocks, sdk.Context) { 30 | t.Helper() 31 | k, m, ctx := SetupPhotonKeeper(t) 32 | return keeper.NewMsgServerImpl(*k), k, m, ctx 33 | } 34 | 35 | func SetupPhotonKeeper(t *testing.T) ( 36 | *keeper.Keeper, 37 | Mocks, 38 | sdk.Context, 39 | ) { 40 | t.Helper() 41 | ctrl := gomock.NewController(t) 42 | m := Mocks{ 43 | AccountKeeper: NewMockAccountKeeper(ctrl), 44 | BankKeeper: NewMockBankKeeper(ctrl), 45 | StakingKeeper: NewMockStakingKeeper(ctrl), 46 | } 47 | 48 | key := storetypes.NewKVStoreKey(types.StoreKey) 49 | testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) 50 | ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()}) 51 | encCfg := moduletestutil.MakeTestEncodingConfig() 52 | types.RegisterInterfaces(encCfg.InterfaceRegistry) 53 | // banktypes.RegisterInterfaces(encCfg.InterfaceRegistry) 54 | authority := authtypes.NewModuleAddress(govtypes.ModuleName).String() 55 | return keeper.NewKeeper(encCfg.Codec, key, authority, m.BankKeeper, m.AccountKeeper, m.StakingKeeper), m, ctx 56 | } 57 | -------------------------------------------------------------------------------- /x/dynamicfee/keeper/query_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 9 | ) 10 | 11 | var _ types.QueryServer = (*QueryServer)(nil) 12 | 13 | // QueryServer defines the gRPC server for the x/dynamicfee module. 14 | type QueryServer struct { 15 | k Keeper 16 | } 17 | 18 | // NewQueryServer creates a new instance of the x/dynamicfee QueryServer type. 19 | func NewQueryServer(keeper Keeper) types.QueryServer { 20 | return &QueryServer{k: keeper} 21 | } 22 | 23 | // Params defines a method that returns the current dynamicfee parameters. 24 | func (q QueryServer) Params(goCtx context.Context, _ *types.ParamsRequest) (*types.ParamsResponse, error) { 25 | ctx := sdk.UnwrapSDKContext(goCtx) 26 | 27 | params, err := q.k.GetParams(ctx) 28 | return &types.ParamsResponse{Params: params}, err 29 | } 30 | 31 | // State defines a method that returns the current dynamicfee state. 32 | func (q QueryServer) State(goCtx context.Context, _ *types.StateRequest) (*types.StateResponse, error) { 33 | ctx := sdk.UnwrapSDKContext(goCtx) 34 | 35 | state, err := q.k.GetState(ctx) 36 | return &types.StateResponse{State: state}, err 37 | } 38 | 39 | // GasPrice defines a method that returns the current dynamicfee base gas price. 40 | func (q QueryServer) GasPrice(goCtx context.Context, req *types.GasPriceRequest) (*types.GasPriceResponse, error) { 41 | ctx := sdk.UnwrapSDKContext(goCtx) 42 | 43 | gasPrice, err := q.k.GetMinGasPrice(ctx, req.GetDenom()) 44 | return &types.GasPriceResponse{Price: gasPrice}, err 45 | } 46 | 47 | // GasPrices defines a method that returns the current dynamicfee list of gas prices. 48 | func (q QueryServer) GasPrices(goCtx context.Context, _ *types.GasPricesRequest) (*types.GasPricesResponse, error) { 49 | ctx := sdk.UnwrapSDKContext(goCtx) 50 | 51 | gasPrices, err := q.k.GetMinGasPrices(ctx) 52 | return &types.GasPricesResponse{Prices: gasPrices}, err 53 | } 54 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/router.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | var _ Router = (*router)(nil) 10 | 11 | // Router implements a governance Handler router. 12 | // 13 | // TODO: Use generic router (ref #3976). 14 | type Router interface { 15 | AddRoute(r string, h Handler) (rtr Router) 16 | HasRoute(r string) bool 17 | GetRoute(path string) (h Handler) 18 | Seal() 19 | } 20 | 21 | type router struct { 22 | routes map[string]Handler 23 | sealed bool 24 | } 25 | 26 | // NewRouter creates a new Router interface instance 27 | func NewRouter() Router { 28 | return &router{ 29 | routes: make(map[string]Handler), 30 | } 31 | } 32 | 33 | // Seal seals the router which prohibits any subsequent route handlers to be 34 | // added. Seal will panic if called more than once. 35 | func (rtr *router) Seal() { 36 | if rtr.sealed { 37 | panic("router already sealed") 38 | } 39 | rtr.sealed = true 40 | } 41 | 42 | // AddRoute adds a governance handler for a given path. It returns the Router 43 | // so AddRoute calls can be linked. It will panic if the router is sealed. 44 | func (rtr *router) AddRoute(path string, h Handler) Router { 45 | if rtr.sealed { 46 | panic("router sealed; cannot add route handler") 47 | } 48 | 49 | if !sdk.IsAlphaNumeric(path) { 50 | panic("route expressions can only contain alphanumeric characters") 51 | } 52 | if rtr.HasRoute(path) { 53 | panic(fmt.Sprintf("route %s has already been initialized", path)) 54 | } 55 | 56 | rtr.routes[path] = h 57 | return rtr 58 | } 59 | 60 | // HasRoute returns true if the router has a path registered or false otherwise. 61 | func (rtr *router) HasRoute(path string) bool { 62 | return rtr.routes[path] != nil 63 | } 64 | 65 | // GetRoute returns a Handler for a given path. 66 | func (rtr *router) GetRoute(path string) Handler { 67 | if !rtr.HasRoute(path) { 68 | panic(fmt.Sprintf("route \"%s\" does not exist", path)) 69 | } 70 | 71 | return rtr.routes[path] 72 | } 73 | -------------------------------------------------------------------------------- /x/dynamicfee/keeper/genesis_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/atomone-hub/atomone/x/dynamicfee/testutil" 7 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestInitGenesis(t *testing.T) { 12 | k, ctx := testutil.SetupKeeper(t, 0) 13 | t.Run("default genesis should not panic", func(t *testing.T) { 14 | require.NotPanics(t, func() { 15 | k.InitGenesis(ctx, *types.DefaultGenesisState()) 16 | }) 17 | }) 18 | 19 | t.Run("default AIMD genesis should not panic", func(t *testing.T) { 20 | require.NotPanics(t, func() { 21 | k.InitGenesis(ctx, *types.DefaultAIMDGenesisState()) 22 | }) 23 | }) 24 | 25 | t.Run("bad genesis state should panic", func(t *testing.T) { 26 | gs := types.DefaultGenesisState() 27 | gs.Params.Window = 0 28 | require.Panics(t, func() { 29 | k.InitGenesis(ctx, *gs) 30 | }) 31 | }) 32 | 33 | t.Run("mismatch in params and state for window should panic", func(t *testing.T) { 34 | gs := types.DefaultAIMDGenesisState() 35 | gs.Params.Window = 1 36 | 37 | require.Panics(t, func() { 38 | k.InitGenesis(ctx, *gs) 39 | }) 40 | }) 41 | } 42 | 43 | func TestExportGenesis(t *testing.T) { 44 | k, ctx := testutil.SetupKeeper(t, 0) 45 | t.Run("export genesis should not panic for default eip-1559", func(t *testing.T) { 46 | gs := types.DefaultGenesisState() 47 | k.InitGenesis(ctx, *gs) 48 | 49 | var exportedGenesis *types.GenesisState 50 | require.NotPanics(t, func() { 51 | exportedGenesis = k.ExportGenesis(ctx) 52 | }) 53 | 54 | require.Equal(t, gs, exportedGenesis) 55 | }) 56 | 57 | t.Run("export genesis should not panic for default AIMD eip-1559", func(t *testing.T) { 58 | gs := types.DefaultAIMDGenesisState() 59 | k.InitGenesis(ctx, *gs) 60 | 61 | var exportedGenesis *types.GenesisState 62 | require.NotPanics(t, func() { 63 | exportedGenesis = k.ExportGenesis(ctx) 64 | }) 65 | 66 | require.Equal(t, gs, exportedGenesis) 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /x/dynamicfee/types/resolver.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | ) 9 | 10 | // DenomResolver is an interface to convert a given token to the dynamicfee's base token. 11 | type DenomResolver interface { 12 | // ConvertToDenom converts deccoin into the equivalent amount of the token denominated in denom. 13 | ConvertToDenom(ctx context.Context, coin sdk.DecCoin, denom string) (sdk.DecCoin, error) 14 | // ExtraDenoms returns a list of denoms in addition of `Params.base_denom` it's possible to pay fees with 15 | ExtraDenoms(ctx context.Context) ([]string, error) 16 | } 17 | 18 | // TestDenomResolver is a test implementation of the DenomResolver interface. It returns "feeCoin.Amount baseDenom" for all coins that are not the baseDenom. 19 | // NOTE: DO NOT USE THIS IN PRODUCTION 20 | type TestDenomResolver struct{} 21 | 22 | // ConvertToDenom returns "coin.Amount denom" for all coins that are not the denom. 23 | func (r *TestDenomResolver) ConvertToDenom(_ context.Context, coin sdk.DecCoin, denom string) (sdk.DecCoin, error) { 24 | if coin.Denom == denom { 25 | return coin, nil 26 | } 27 | 28 | return sdk.NewDecCoinFromDec(denom, coin.Amount), nil 29 | } 30 | 31 | func (r *TestDenomResolver) ExtraDenoms(_ context.Context) ([]string, error) { 32 | return []string{}, nil 33 | } 34 | 35 | // ErrorDenomResolver is a test implementation of the DenomResolver interface. It returns an error for all coins that are not the baseDenom. 36 | // NOTE: DO NOT USE THIS IN PRODUCTION 37 | type ErrorDenomResolver struct{} 38 | 39 | // ConvertToDenom returns an error for all coins that are not the denom. 40 | func (r *ErrorDenomResolver) ConvertToDenom(_ context.Context, coin sdk.DecCoin, denom string) (sdk.DecCoin, error) { 41 | if coin.Denom == denom { 42 | return coin, nil 43 | } 44 | 45 | return sdk.DecCoin{}, fmt.Errorf("error resolving denom") 46 | } 47 | 48 | func (r *ErrorDenomResolver) ExtraDenoms(_ context.Context) ([]string, error) { 49 | return []string{}, nil 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/nightly-tests.yml: -------------------------------------------------------------------------------- 1 | name: "Nightly E2E run" 2 | on: 3 | workflow_call: 4 | workflow_dispatch: 5 | schedule: 6 | # run every day at 03:00 UTC 7 | - cron: "0 3 * * *" 8 | 9 | jobs: 10 | 11 | run-tests: 12 | uses: atomone-hub/atomone/.github/workflows/test.yml@main 13 | 14 | run-simulations: 15 | uses: atomone-hub/atomone/.github/workflows/sims.yml@main 16 | 17 | run-vulncheck: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 5 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: actions/setup-go@v5 23 | with: 24 | go-version-file: go.mod 25 | - name: run-vulncheck 26 | id: vulncheck 27 | run: make vulncheck 28 | 29 | warn-if-failure: 30 | if: failure() 31 | needs: [ run-tests, run-vulncheck, run-simulations] 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Notify Slack on failure 35 | uses: slackapi/slack-github-action@v1.25.0 36 | env: 37 | SLACK_WEBHOOK_URL: ${{ secrets.NIGHTLY_E2E_SLACK_WEBHOOK_URL }} 38 | SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK 39 | BRANCH: ${{ github.ref_name }} 40 | RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" 41 | COMMITS_URL: "${{ github.server_url }}/${{ github.repository }}/commits/${{ github.ref_name }}" 42 | with: 43 | payload: | 44 | { 45 | "blocks": [ 46 | { 47 | "type": "header", 48 | "text": { 49 | "type": "plain_text", 50 | "text": "❗Nightly tests failed", 51 | "emoji": true 52 | } 53 | }, 54 | { 55 | "type": "section", 56 | "text": { 57 | "type": "mrkdwn", 58 | "text": "See the <${{ env.RUN_URL }}|run details>" 59 | } 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | --- 2 | project_name: atomone 3 | 4 | builds: 5 | - main: ./cmd/atomoned 6 | id: "atomoned" 7 | binary: atomoned 8 | mod_timestamp: "{{ .CommitTimestamp }}" 9 | flags: 10 | - -tags=netgo 11 | - -trimpath 12 | env: 13 | - CGO_ENABLED=0 14 | ldflags: 15 | # .Env.TM_VERSION is provided in the workflow runner environment -> see .github/workflows/release.yml 16 | - -X github.com/cosmos/cosmos-sdk/version.Name=atomone -X github.com/cosmos/cosmos-sdk/version.AppName=atomoned -X github.com/cosmos/cosmos-sdk/version.Version=v{{ .Version }} -X github.com/cosmos/cosmos-sdk/version.Commit={{ .Commit }} -X github.com/cosmos/cosmos-sdk/version.BuildTags=netgo -X github.com/cometbft/cometbft/version.TMCoreSemVer={{ .Env.TM_VERSION }} -w -s 17 | goos: 18 | - darwin 19 | - linux 20 | - windows 21 | goarch: 22 | - amd64 23 | - arm64 24 | 25 | archives: 26 | # disables archiving; to enable use commented lines below 27 | - format: binary 28 | name_template: "{{ .Binary }}-v{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" 29 | 30 | # - format: tar.gz 31 | # wrap_in_directory: "true" 32 | # format_overrides: 33 | # - goos: windows 34 | # format: zip 35 | # name_template: "{{ .Binary }}-v{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" 36 | # files: 37 | # - LICENSE 38 | # - README.md 39 | # rlcp: true 40 | 41 | release: 42 | prerelease: true 43 | name_template: "v{{.Version}}" 44 | 45 | checksum: 46 | name_template: SHA256SUMS-v{{.Version}}.txt 47 | algorithm: sha256 48 | 49 | snapshot: 50 | name_template: "{{ .Version }}-{{ .ShortCommit }}" 51 | 52 | changelog: 53 | disable: true 54 | 55 | git: 56 | # What should be used to sort tags when gathering the current and previous 57 | # tags if there are more than one tag in the same commit. 58 | # 59 | # source: https://goreleaser.com/customization/git/ 60 | tag_sort: -version:refname 61 | prerelease_suffix: "-rc" 62 | -------------------------------------------------------------------------------- /x/dynamicfee/testutil/keeper.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "testing" 5 | 6 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 7 | tmtime "github.com/cometbft/cometbft/types/time" 8 | 9 | storetypes "cosmossdk.io/store/types" 10 | 11 | "github.com/cosmos/cosmos-sdk/testutil" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 14 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 15 | 16 | "github.com/atomone-hub/atomone/x/dynamicfee/keeper" 17 | "github.com/atomone-hub/atomone/x/dynamicfee/types" 18 | govtypes "github.com/atomone-hub/atomone/x/gov/types" 19 | ) 20 | 21 | func SetupMsgServer(t *testing.T, maxBlockGas uint64) (types.MsgServer, *keeper.Keeper, sdk.Context) { 22 | t.Helper() 23 | k, ctx := SetupKeeper(t, maxBlockGas) 24 | return keeper.NewMsgServer(k), k, ctx 25 | } 26 | 27 | func SetupQueryServer(t *testing.T, maxBlockGas uint64) (types.QueryServer, *keeper.Keeper, sdk.Context) { 28 | t.Helper() 29 | k, ctx := SetupKeeper(t, maxBlockGas) 30 | return keeper.NewQueryServer(*k), k, ctx 31 | } 32 | 33 | const MaxBlockGas = 30_000_000 34 | 35 | func SetupKeeper(t *testing.T, maxBlockGas uint64) (*keeper.Keeper, sdk.Context) { 36 | t.Helper() 37 | 38 | key := storetypes.NewKVStoreKey(types.StoreKey) 39 | testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) 40 | ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()}) 41 | // setup block max gas 42 | if maxBlockGas == 0 { 43 | maxBlockGas = MaxBlockGas 44 | } 45 | ctx = ctx.WithConsensusParams(tmproto.ConsensusParams{Block: &tmproto.BlockParams{MaxGas: int64(maxBlockGas)}}) 46 | encCfg := moduletestutil.MakeTestEncodingConfig() 47 | types.RegisterInterfaces(encCfg.InterfaceRegistry) 48 | // banktypes.RegisterInterfaces(encCfg.InterfaceRegistry) 49 | authority := authtypes.NewModuleAddress(govtypes.ModuleName).String() 50 | 51 | return keeper.NewKeeper(encCfg.Codec, key, &types.ErrorDenomResolver{}, authority), ctx 52 | } 53 | -------------------------------------------------------------------------------- /app/upgrades/v4/upgrades.go: -------------------------------------------------------------------------------- 1 | package v4 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "cosmossdk.io/math" 8 | upgradetypes "cosmossdk.io/x/upgrade/types" 9 | 10 | "github.com/cosmos/cosmos-sdk/types/module" 11 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 12 | govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" 13 | sdkgov "github.com/cosmos/cosmos-sdk/x/gov/types" 14 | sdkgovv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 15 | 16 | "github.com/atomone-hub/atomone/app/keepers" 17 | ) 18 | 19 | // CreateUpgradeHandler returns a upgrade handler for AtomOne v4 20 | // This versions contains the upgrade to Cosmos SDK v0.50 and IBC v10 21 | func CreateUpgradeHandler( 22 | mm *module.Manager, 23 | configurator module.Configurator, 24 | keepers *keepers.AppKeepers, 25 | ) upgradetypes.UpgradeHandler { 26 | return func(ctx context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { 27 | vm, err := mm.RunMigrations(ctx, configurator, vm) 28 | if err != nil { 29 | return vm, err 30 | } 31 | 32 | if err := initGovParams(ctx, keepers.GovKeeper); err != nil { 33 | return vm, err 34 | } 35 | 36 | return vm, nil 37 | } 38 | } 39 | 40 | // initGovParams initializes the missing gov modules added in AtomOne SDK v0.50. 41 | func initGovParams(ctx context.Context, govKeeper *govkeeper.Keeper) error { 42 | params, err := govKeeper.Params.Get(ctx) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | defaultParams := sdkgovv1.DefaultParams() 48 | params.ProposalCancelRatio = defaultParams.ProposalCancelRatio 49 | params.ProposalCancelDest = authtypes.NewModuleAddress(sdkgov.ModuleName).String() 50 | params.MinDepositRatio = defaultParams.MinDepositRatio 51 | params.GovernorStatusChangePeriod = defaultParams.GovernorStatusChangePeriod 52 | params.MinGovernorSelfDelegation = math.NewInt(10000_000000).String() // to be elegible as governor must have 10K ATONE staked 53 | 54 | if err := govKeeper.Params.Set(ctx, params); err != nil { 55 | return fmt.Errorf("failed to set gov params: %w", err) 56 | } 57 | 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/codec.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | upgradetypes "cosmossdk.io/x/upgrade/types" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/codec/legacy" 8 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/cosmos/cosmos-sdk/types/msgservice" 11 | paramsproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" 12 | ) 13 | 14 | // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the 15 | // governance module. 16 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 17 | cdc.RegisterInterface((*Content)(nil), nil) 18 | legacy.RegisterAminoMsg(cdc, &MsgSubmitProposal{}, "atomone/MsgSubmitProposal") 19 | legacy.RegisterAminoMsg(cdc, &MsgDeposit{}, "atomone/MsgDeposit") 20 | legacy.RegisterAminoMsg(cdc, &MsgVote{}, "atomone/MsgVote") 21 | legacy.RegisterAminoMsg(cdc, &MsgVoteWeighted{}, "atomone/MsgVoteWeighted") 22 | cdc.RegisterConcrete(&TextProposal{}, "atomone/TextProposal", nil) 23 | } 24 | 25 | // RegisterInterfaces registers the interfaces types with the Interface Registry. 26 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 27 | registry.RegisterImplementations((*sdk.Msg)(nil), 28 | &MsgSubmitProposal{}, 29 | &MsgVote{}, 30 | &MsgVoteWeighted{}, 31 | &MsgDeposit{}, 32 | ) 33 | registry.RegisterInterface( 34 | "atomone.gov.v1beta1.Content", 35 | (*Content)(nil), 36 | &TextProposal{}, 37 | ) 38 | 39 | // Register proposal types (this is actually done in related modules, but 40 | // since we are using an other gov module, we need to do it manually). 41 | registry.RegisterImplementations( 42 | (*Content)(nil), 43 | ¶msproposal.ParameterChangeProposal{}, 44 | ) 45 | registry.RegisterImplementations( 46 | (*Content)(nil), 47 | &upgradetypes.SoftwareUpgradeProposal{}, //nolint:staticcheck 48 | ) 49 | registry.RegisterImplementations( 50 | (*Content)(nil), 51 | &upgradetypes.CancelSoftwareUpgradeProposal{}, //nolint:staticcheck 52 | ) 53 | 54 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 55 | } 56 | -------------------------------------------------------------------------------- /x/photon/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | "github.com/cosmos/cosmos-sdk/client/tx" 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | "github.com/cosmos/cosmos-sdk/version" 13 | 14 | "github.com/atomone-hub/atomone/x/photon/types" 15 | ) 16 | 17 | // GetTxCmd returns the transaction commands for this module 18 | func GetTxCmd() *cobra.Command { 19 | cmd := &cobra.Command{ 20 | Use: types.ModuleName, 21 | Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), 22 | DisableFlagParsing: true, 23 | SuggestionsMinimumDistance: 2, 24 | RunE: client.ValidateCmd, 25 | } 26 | cmd.AddCommand(GetTxMintPhotonCmd()) 27 | return cmd 28 | } 29 | 30 | func GetTxMintPhotonCmd() *cobra.Command { 31 | cmd := &cobra.Command{ 32 | Use: "mint [to_key_or_address] [amount]", 33 | Short: "Broadcast MintPhoton message which burns [amount] and mint photons.", 34 | Long: `Mint photons by burning the specified [amount]. 35 | The amount to burn must be specified in the bond denomination. 36 | Note, the '--from' flag is ignored as it is implied from [to_key_or_address].`, 37 | Example: fmt.Sprintf(`%s tx photon mint atom1... 1000000uatone`, version.AppName), 38 | Args: cobra.ExactArgs(2), 39 | RunE: func(cmd *cobra.Command, args []string) (err error) { 40 | err = cmd.Flags().Set(flags.FlagFrom, args[0]) 41 | if err != nil { 42 | return err 43 | } 44 | clientCtx, err := client.GetClientTxContext(cmd) 45 | if err != nil { 46 | return err 47 | } 48 | toBurn, err := sdk.ParseCoinNormalized(args[1]) 49 | if err != nil { 50 | return err 51 | } 52 | msg := types.NewMsgMintPhoton( 53 | clientCtx.GetFromAddress(), 54 | toBurn, 55 | ) 56 | if err := msg.ValidateBasic(); err != nil { 57 | return err 58 | } 59 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 60 | }, 61 | } 62 | flags.AddTxFlagsToCmd(cmd) 63 | return cmd 64 | } 65 | -------------------------------------------------------------------------------- /x/gov/types/v1/codec.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/cosmos/cosmos-sdk/codec/legacy" 6 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/msgservice" 9 | ) 10 | 11 | // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the 12 | // governance module. 13 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 14 | legacy.RegisterAminoMsg(cdc, &MsgSubmitProposal{}, "atomone/v1/MsgSubmitProposal") 15 | legacy.RegisterAminoMsg(cdc, &MsgDeposit{}, "atomone/v1/MsgDeposit") 16 | legacy.RegisterAminoMsg(cdc, &MsgVote{}, "atomone/v1/MsgVote") 17 | legacy.RegisterAminoMsg(cdc, &MsgVoteWeighted{}, "atomone/v1/MsgVoteWeighted") 18 | legacy.RegisterAminoMsg(cdc, &MsgExecLegacyContent{}, "atomone/v1/MsgExecLegacyContent") 19 | legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "atomone/x/gov/v1/MsgUpdateParams") 20 | legacy.RegisterAminoMsg(cdc, &MsgProposeConstitutionAmendment{}, "atomone/x/gov/v1/MsgProposeAmendment") 21 | legacy.RegisterAminoMsg(cdc, &MsgProposeLaw{}, "atomone/x/gov/v1/MsgProposeLaw") 22 | legacy.RegisterAminoMsg(cdc, &MsgCreateGovernor{}, "atomone/v1/MsgCreateGovernor") 23 | legacy.RegisterAminoMsg(cdc, &MsgEditGovernor{}, "atomone/v1/MsgEditGovernor") 24 | legacy.RegisterAminoMsg(cdc, &MsgDelegateGovernor{}, "atomone/v1/MsgDelegateGovernor") 25 | legacy.RegisterAminoMsg(cdc, &MsgUndelegateGovernor{}, "atomone/v1/MsgUndelegateGovernor") 26 | } 27 | 28 | // RegisterInterfaces registers the interfaces types with the Interface Registry. 29 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 30 | registry.RegisterImplementations((*sdk.Msg)(nil), 31 | &MsgSubmitProposal{}, 32 | &MsgVote{}, 33 | &MsgVoteWeighted{}, 34 | &MsgDeposit{}, 35 | &MsgExecLegacyContent{}, 36 | &MsgUpdateParams{}, 37 | &MsgProposeConstitutionAmendment{}, 38 | &MsgProposeLaw{}, 39 | &MsgCreateGovernor{}, 40 | &MsgEditGovernor{}, 41 | &MsgDelegateGovernor{}, 42 | &MsgUndelegateGovernor{}, 43 | ) 44 | 45 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "**.go" 7 | push: 8 | branches: 9 | - main 10 | - release/v* 11 | - feat/** 12 | paths: 13 | - "**.go" 14 | 15 | jobs: 16 | analyze: 17 | name: Analyze 18 | runs-on: ubuntu-latest 19 | permissions: 20 | actions: read 21 | contents: read 22 | security-events: write 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@v4 27 | - uses: actions/setup-go@v5 28 | with: 29 | go-version-file: go.mod 30 | 31 | # Initializes the CodeQL tools for scanning. 32 | - name: Initialize CodeQL 33 | uses: github/codeql-action/init@v3 34 | with: 35 | languages: "go" 36 | # If you wish to specify custom queries, you can do so here or in a config file. 37 | # By default, queries listed here will override any specified in a config file. 38 | # Prefix the list here with "+" to use these queries and those in the config file. 39 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 40 | queries: +security-and-quality,github/codeql/go/ql/src/experimental/InconsistentCode/DeferInLoop.ql@main,github/codeql/go/ql/src/experimental/Unsafe/WrongUsageOfUnsafe.ql@main,github/codeql/go/ql/src/experimental/CWE-369/DivideByZero.ql@main 41 | packs: +crypto-com/cosmos-sdk-codeql 42 | 43 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 44 | # If this step fails, then you should remove it and run the build manually (see below) 45 | - name: Autobuild 46 | uses: github/codeql-action/autobuild@v3 47 | 48 | # ℹ️ Command-line programs to run using the OS shell. 49 | # 📚 https://git.io/JvXDl 50 | 51 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 52 | # and modify them (or add more) to build your code if your project 53 | # uses a compiled language 54 | 55 | #- run: | 56 | # make bootstrap 57 | # make release 58 | 59 | - name: Perform CodeQL Analysis 60 | uses: github/codeql-action/analyze@v3 61 | -------------------------------------------------------------------------------- /x/photon/keeper/grpc_query_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | appparams "github.com/atomone-hub/atomone/app/params" 9 | "github.com/atomone-hub/atomone/x/photon/testutil" 10 | "github.com/atomone-hub/atomone/x/photon/types" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestParamsQuery(t *testing.T) { 15 | k, _, ctx := testutil.SetupPhotonKeeper(t) 16 | params := types.DefaultParams() 17 | k.SetParams(ctx, params) 18 | 19 | resp, err := k.Params(ctx, &types.QueryParamsRequest{}) 20 | 21 | require.NoError(t, err) 22 | require.Equal(t, &types.QueryParamsResponse{Params: params}, resp) 23 | } 24 | 25 | func TestConversionRateQuery(t *testing.T) { 26 | tests := []struct { 27 | name string 28 | uatoneSupply int64 29 | uphotonSupply int64 30 | expectedResponse *types.QueryConversionRateResponse 31 | }{ 32 | { 33 | name: "nominal case", 34 | uatoneSupply: 100_000_000_000_000, // 100,000,000atone 35 | uphotonSupply: 100_000_000_000, // 100,000photon 36 | expectedResponse: &types.QueryConversionRateResponse{ 37 | ConversionRate: "9.999000000000000000", 38 | }, 39 | }, 40 | { 41 | name: "max supply of photon exceeded", 42 | uatoneSupply: 100_000_000_000_000, // 100,000,000atone 43 | uphotonSupply: types.MaxSupply + 1, 44 | expectedResponse: &types.QueryConversionRateResponse{ 45 | ConversionRate: "0.000000000000000000", 46 | }, 47 | }, 48 | } 49 | for _, tt := range tests { 50 | t.Run(tt.name, func(t *testing.T) { 51 | k, m, ctx := testutil.SetupPhotonKeeper(t) 52 | m.StakingKeeper.EXPECT().BondDenom(ctx).Return(appparams.BondDenom, nil) 53 | m.BankKeeper.EXPECT().GetSupply(ctx, appparams.BondDenom). 54 | Return(sdk.NewInt64Coin(appparams.BondDenom, tt.uatoneSupply)) 55 | m.BankKeeper.EXPECT().GetSupply(ctx, types.Denom). 56 | Return(sdk.NewInt64Coin(appparams.BondDenom, tt.uphotonSupply)) 57 | 58 | resp, err := k.ConversionRate(ctx, &types.QueryConversionRateRequest{}) 59 | 60 | require.NoError(t, err) 61 | require.Equal(t, tt.expectedResponse, resp) 62 | }) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /x/coredaos/simulation/proposals.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/address" 9 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 10 | "github.com/cosmos/cosmos-sdk/x/simulation" 11 | 12 | "github.com/atomone-hub/atomone/x/coredaos/types" 13 | ) 14 | 15 | // Simulation operation weights constants 16 | const ( 17 | DefaultWeightMsgUpdateParams int = 100 18 | 19 | OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec 20 | ) 21 | 22 | // ProposalMsgs defines the module weighted proposals' contents 23 | func ProposalMsgs() []simtypes.WeightedProposalMsg { 24 | return []simtypes.WeightedProposalMsg{ 25 | simulation.NewWeightedProposalMsg( 26 | OpWeightMsgUpdateParams, 27 | DefaultWeightMsgUpdateParams, 28 | SimulateMsgUpdateParams, 29 | ), 30 | } 31 | } 32 | 33 | // SimulateMsgUpdateParams returns a random MsgUpdateParams 34 | func SimulateMsgUpdateParams(r *rand.Rand, ctx sdk.Context, _ []simtypes.Account) sdk.Msg { 35 | // use the default gov module account address as authority 36 | var authority sdk.AccAddress = address.Module("gov") 37 | 38 | params := types.DefaultParams() 39 | 40 | params.VotingPeriodExtensionsLimit = uint32(simtypes.RandIntBetween(r, 0, 10)) // Random limit between 0 and 9 41 | votingPeriodExtensionDuration := time.Duration(simtypes.RandIntBetween(r, 1, 60*60*6)) * time.Second // Random duration between 1 second and 6 hours 42 | params.VotingPeriodExtensionDuration = &votingPeriodExtensionDuration 43 | 44 | randInt := r.Intn(2) 45 | if randInt%2 == 0 { 46 | SteeringDaoAccount := simtypes.RandomAccounts(r, 1)[0] 47 | params.SteeringDaoAddress = SteeringDaoAccount.Address.String() 48 | } else { 49 | params.SteeringDaoAddress = "" 50 | } 51 | 52 | randInt = r.Intn(2) 53 | if randInt%2 == 0 { 54 | OversightDaoAccount := simtypes.RandomAccounts(r, 1)[0] 55 | params.OversightDaoAddress = OversightDaoAccount.Address.String() 56 | } else { 57 | params.OversightDaoAddress = "" 58 | } 59 | 60 | return &types.MsgUpdateParams{ 61 | Authority: authority.String(), 62 | Params: params, 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /x/photon/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | 11 | "github.com/atomone-hub/atomone/x/photon/types" 12 | ) 13 | 14 | // GetQueryCmd returns the cli query commands for this module 15 | func GetQueryCmd(queryRoute string) *cobra.Command { 16 | // Group photon queries under a subcommand 17 | cmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | 25 | cmd.AddCommand( 26 | GetQueryParamsCmd(), 27 | GetQueryConversionRateCmd(), 28 | ) 29 | return cmd 30 | } 31 | 32 | func GetQueryParamsCmd() *cobra.Command { 33 | cmd := &cobra.Command{ 34 | Use: "params", 35 | Short: "shows the parameters of the module", 36 | Args: cobra.NoArgs, 37 | RunE: func(cmd *cobra.Command, args []string) error { 38 | clientCtx, err := client.GetClientQueryContext(cmd) 39 | if err != nil { 40 | return err 41 | } 42 | queryClient := types.NewQueryClient(clientCtx) 43 | res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) 44 | if err != nil { 45 | return err 46 | } 47 | return clientCtx.PrintProto(res) 48 | }, 49 | } 50 | flags.AddQueryFlagsToCmd(cmd) 51 | return cmd 52 | } 53 | 54 | func GetQueryConversionRateCmd() *cobra.Command { 55 | cmd := &cobra.Command{ 56 | Use: "conversion-rate", 57 | Short: "shows the atone to photon conversion rate", 58 | Args: cobra.NoArgs, 59 | RunE: func(cmd *cobra.Command, args []string) error { 60 | clientCtx, err := client.GetClientQueryContext(cmd) 61 | if err != nil { 62 | return err 63 | } 64 | queryClient := types.NewQueryClient(clientCtx) 65 | res, err := queryClient.ConversionRate(cmd.Context(), &types.QueryConversionRateRequest{}) 66 | if err != nil { 67 | return err 68 | } 69 | return clientCtx.PrintProto(res) 70 | }, 71 | } 72 | flags.AddQueryFlagsToCmd(cmd) 73 | return cmd 74 | } 75 | -------------------------------------------------------------------------------- /x/photon/keeper/keeper.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "cosmossdk.io/log" 8 | "cosmossdk.io/math" 9 | storetypes "cosmossdk.io/store/types" 10 | 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | 14 | "github.com/atomone-hub/atomone/x/photon/types" 15 | ) 16 | 17 | type Keeper struct { 18 | cdc codec.BinaryCodec 19 | storeKey storetypes.StoreKey 20 | authority string 21 | 22 | bankKeeper types.BankKeeper 23 | accountKeeper types.AccountKeeper 24 | stakingKeeper types.StakingKeeper 25 | } 26 | 27 | func NewKeeper( 28 | cdc codec.BinaryCodec, 29 | storeKey storetypes.StoreKey, 30 | authority string, 31 | bankKeeper types.BankKeeper, 32 | accountKeeper types.AccountKeeper, 33 | stakingKeeper types.StakingKeeper, 34 | ) *Keeper { 35 | return &Keeper{ 36 | cdc: cdc, 37 | storeKey: storeKey, 38 | authority: authority, 39 | bankKeeper: bankKeeper, 40 | accountKeeper: accountKeeper, 41 | stakingKeeper: stakingKeeper, 42 | } 43 | } 44 | 45 | func (k Keeper) Logger(ctx sdk.Context) log.Logger { 46 | return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) 47 | } 48 | 49 | // PhotonConversionRate returns the conversion rate for converting bond denom to 50 | // photon. 51 | // NOTE: bondDenomSupply cannot be zero when the chain is producing blocks (thus it can never be zero). 52 | // This is because the only way for validators to be able to participate in block production is to have 53 | // staked bond denom, which therefore is locked and cannot be burned. Although this condition is logically 54 | // impossible, we still add a panic here to be defensive. 55 | func (k Keeper) PhotonConversionRate(_ context.Context, bondDenomSupply, uphotonSupply math.LegacyDec) math.LegacyDec { 56 | remainMintableUphotons := math.LegacyNewDec(types.MaxSupply).Sub(uphotonSupply) 57 | if remainMintableUphotons.IsNegative() { 58 | // If for any reason the max supply is exceeded, avoid returning a negative number 59 | return math.LegacyZeroDec() 60 | } 61 | if bondDenomSupply.IsZero() { 62 | panic("bond denom supply cannot be zero") 63 | } 64 | return remainMintableUphotons.Quo(bondDenomSupply) 65 | } 66 | -------------------------------------------------------------------------------- /app/genesis_account.go: -------------------------------------------------------------------------------- 1 | package atomone 2 | 3 | import ( 4 | "errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 8 | ) 9 | 10 | var _ authtypes.GenesisAccount = (*SimGenesisAccount)(nil) 11 | 12 | // SimGenesisAccount defines a type that implements the GenesisAccount interface 13 | // to be used for simulation accounts in the genesis state. 14 | type SimGenesisAccount struct { 15 | *authtypes.BaseAccount 16 | 17 | // vesting account fields 18 | OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"` // total vesting coins upon initialization 19 | DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"` // delegated vested coins at time of delegation 20 | DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"` // delegated vesting coins at time of delegation 21 | StartTime int64 `json:"start_time" yaml:"start_time"` // vesting start time (UNIX Epoch time) 22 | EndTime int64 `json:"end_time" yaml:"end_time"` // vesting end time (UNIX Epoch time) 23 | 24 | // module account fields 25 | ModuleName string `json:"module_name" yaml:"module_name"` // name of the module account 26 | ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"` // permissions of module account 27 | } 28 | 29 | // Validate checks for errors on the vesting and module account parameters 30 | func (sga SimGenesisAccount) Validate() error { 31 | if sga.OriginalVesting.IsAnyNil() { 32 | return errors.New("OriginalVesting amount must not be nil") 33 | } 34 | 35 | if !sga.OriginalVesting.IsZero() { 36 | if sga.StartTime >= sga.EndTime { 37 | return errors.New("vesting start-time cannot be before end-time") 38 | } 39 | } 40 | 41 | if sga.BaseAccount == nil { 42 | return errors.New("BaseAccount must not be nil") 43 | } 44 | 45 | if sga.ModuleName != "" { 46 | ma := authtypes.ModuleAccount{ 47 | BaseAccount: sga.BaseAccount, Name: sga.ModuleName, Permissions: sga.ModulePermissions, 48 | } 49 | 50 | if err := ma.Validate(); err != nil { 51 | return err 52 | } 53 | } 54 | 55 | return sga.BaseAccount.Validate() 56 | } 57 | -------------------------------------------------------------------------------- /x/coredaos/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/atomone-hub/atomone/x/coredaos/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestGenesisState_Validate(t *testing.T) { 12 | tests := []struct { 13 | desc string 14 | genState func() *types.GenesisState 15 | valid bool 16 | }{ 17 | { 18 | desc: "default is valid", 19 | genState: types.DefaultGenesis, 20 | valid: true, 21 | }, 22 | { 23 | desc: "valid genesis state", 24 | genState: func() *types.GenesisState { 25 | params := types.DefaultParams() 26 | return &types.GenesisState{Params: params} 27 | }, 28 | valid: true, 29 | }, 30 | { 31 | desc: "invalid genesis state nil extension duration", 32 | genState: func() *types.GenesisState { 33 | params := types.DefaultParams() 34 | params.VotingPeriodExtensionDuration = nil 35 | return &types.GenesisState{Params: params} 36 | }, 37 | valid: false, 38 | }, 39 | { 40 | desc: "invalid genesis state wrong oversightdaoaddress", 41 | genState: func() *types.GenesisState { 42 | params := types.DefaultParams() 43 | params.OversightDaoAddress = "cosmosincorrectaddress" 44 | return &types.GenesisState{Params: params} 45 | }, 46 | valid: false, 47 | }, 48 | { 49 | desc: "invalid genesis state wrong steeringdaoaddress", 50 | genState: func() *types.GenesisState { 51 | params := types.DefaultParams() 52 | params.SteeringDaoAddress = "cosmosincorrectaddress" 53 | return &types.GenesisState{Params: params} 54 | }, 55 | valid: false, 56 | }, 57 | { 58 | desc: "invalid genesis state negative extension duration", 59 | genState: func() *types.GenesisState { 60 | negativeTimeDuration := time.Duration(-1) 61 | params := types.DefaultParams() 62 | params.VotingPeriodExtensionDuration = &negativeTimeDuration 63 | return &types.GenesisState{Params: params} 64 | }, 65 | valid: false, 66 | }, 67 | } 68 | for _, tc := range tests { 69 | t.Run(tc.desc, func(t *testing.T) { 70 | err := tc.genState().Validate() 71 | if tc.valid { 72 | require.NoError(t, err) 73 | } else { 74 | require.Error(t, err) 75 | } 76 | }) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/tally.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "cosmossdk.io/math" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // ValidatorGovInfo used for tallying 10 | type ValidatorGovInfo struct { 11 | Address sdk.ValAddress // address of the validator operator 12 | BondedTokens math.Int // Power of a Validator 13 | DelegatorShares math.LegacyDec // Total outstanding delegator shares 14 | DelegatorDeductions math.LegacyDec // Delegator deductions from validator's delegators voting independently 15 | Vote WeightedVoteOptions // Vote of the validator 16 | } 17 | 18 | // NewValidatorGovInfo creates a ValidatorGovInfo instance 19 | func NewValidatorGovInfo(address sdk.ValAddress, bondedTokens math.Int, delegatorShares, 20 | delegatorDeductions math.LegacyDec, options WeightedVoteOptions, 21 | ) ValidatorGovInfo { 22 | return ValidatorGovInfo{ 23 | Address: address, 24 | BondedTokens: bondedTokens, 25 | DelegatorShares: delegatorShares, 26 | DelegatorDeductions: delegatorDeductions, 27 | Vote: options, 28 | } 29 | } 30 | 31 | // NewTallyResult creates a new TallyResult instance 32 | func NewTallyResult(yes, abstain, no, noWithVeto math.Int) TallyResult { 33 | return TallyResult{ 34 | Yes: yes, 35 | Abstain: abstain, 36 | No: no, 37 | NoWithVeto: noWithVeto, 38 | } 39 | } 40 | 41 | // NewTallyResultFromMap creates a new TallyResult instance from a Option -> Dec map 42 | func NewTallyResultFromMap(results map[VoteOption]math.LegacyDec) TallyResult { 43 | return NewTallyResult( 44 | results[OptionYes].TruncateInt(), 45 | results[OptionAbstain].TruncateInt(), 46 | results[OptionNo].TruncateInt(), 47 | results[OptionNoWithVeto].TruncateInt(), 48 | ) 49 | } 50 | 51 | // EmptyTallyResult returns an empty TallyResult. 52 | func EmptyTallyResult() TallyResult { 53 | return NewTallyResult(math.ZeroInt(), math.ZeroInt(), math.ZeroInt(), math.ZeroInt()) 54 | } 55 | 56 | // Equals returns if two proposals are equal. 57 | func (tr TallyResult) Equals(comp TallyResult) bool { 58 | return tr.Yes.Equal(comp.Yes) && 59 | tr.Abstain.Equal(comp.Abstain) && 60 | tr.No.Equal(comp.No) && 61 | tr.NoWithVeto.Equal(comp.NoWithVeto) 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AtomOne 2 | 3 | AtomOne is built using the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) as 4 | a fork of the [Cosmos Hub](https://github.com/cosmos/gaia) at version 5 | [v15.2.0](https://github.com/cosmos/gaia/releases/tag/v15.2.0) (common commit 6 | hash 7281c9b). 7 | 8 | The following modifications have been made to the Cosmos Hub software to create AtomOne: 9 | 10 | 1. Removed x/globalfee module and revert to older and simpler fee decorator 11 | 2. Removed Packet Forwarding Middleware 12 | 3. Removed Interchain Security module 13 | 4. Reverted to standard Cosmos SDK v0.47.10 without the Liquid Staking Module (LSM) 14 | 5. Changed Bech32 prefixes to `atone` (see `cmd/atomoned/cmd/config.go`) 15 | 6. Removed ability for validators to vote on proposals with delegations, they can 16 | only use their own stake 17 | 18 | ## Reproducible builds 19 | 20 | An effort has been made to make it possible to build the exact same binary 21 | locally as the Github Release section. To do this: 22 | 23 | - Checkout to the expected released version 24 | - Run `make build` (which will output the binary to the `build` directory) or 25 | `make install`. Note that a fixed version of the `go` binary is required, 26 | follow the command instructions to install this specific version if needed. 27 | - The resulted binary should have the same sha256 hash than the one from the 28 | Github Release section. 29 | 30 | ## Ledger support 31 | 32 | Run `make build/install LEDGER_ENABLED=true` to have ledger support in 33 | `atomoned` binary. 34 | 35 | Note that this will disable reproducible builds, as it introduces OS 36 | dependencies. 37 | 38 | ## Genesis file 39 | 40 | The proposed genesis files for atomone can be found in the [genesis repo](https://github.com/atomone-hub/genesis). 41 | 42 | ## Public RPC and fullnode endpoints 43 | 44 | The public RPC and fullnode endpoints directory can be found in the [atom.one](https://atom.one) 45 | website. 46 | 47 | ## Acknowledgements 48 | 49 | Portions of this codebase are copied or adapted from 50 | [cosmos/gaia@v15](https://github.com/cosmos/gaia/tree/v15.0.0), 51 | [cosmos/cosmos-sdk@v47.10](https://github.com/cosmos/cosmos-sdk/tree/v0.47.10) 52 | and [skip-mev/feemarket@v1.1.1](https://github.com/skip-mev/feemarket/tree/v1.1.1). 53 | 54 | Their original licenses are both included in [ATTRIBUTION](ATTRIBUTION) 55 | -------------------------------------------------------------------------------- /x/gov/types/v1/tally.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "cosmossdk.io/math" 5 | 6 | sdkgovtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 7 | ) 8 | 9 | // GovernorGovInfo used for tallying 10 | type GovernorGovInfo struct { 11 | Address sdkgovtypes.GovernorAddress // address of the governor 12 | ValShares map[string]math.LegacyDec // shares held for each validator 13 | ValSharesDeductions map[string]math.LegacyDec // deductions from validator's shares when a delegator votes independently 14 | Vote WeightedVoteOptions // vote of the governor 15 | } 16 | 17 | // NewGovernorGovInfo creates a GovernorGovInfo instance 18 | func NewGovernorGovInfo(address sdkgovtypes.GovernorAddress, valShares []GovernorValShares, options WeightedVoteOptions) GovernorGovInfo { 19 | valSharesMap := make(map[string]math.LegacyDec) 20 | valSharesDeductionsMap := make(map[string]math.LegacyDec) 21 | for _, valShare := range valShares { 22 | valSharesMap[valShare.ValidatorAddress] = valShare.Shares 23 | valSharesDeductionsMap[valShare.ValidatorAddress] = math.LegacyZeroDec() 24 | } 25 | 26 | return GovernorGovInfo{ 27 | Address: address, 28 | ValShares: valSharesMap, 29 | ValSharesDeductions: valSharesDeductionsMap, 30 | Vote: options, 31 | } 32 | } 33 | 34 | // NewTallyResult creates a new TallyResult instance 35 | func NewTallyResult(yes, abstain, no math.Int) TallyResult { 36 | return TallyResult{ 37 | YesCount: yes.String(), 38 | AbstainCount: abstain.String(), 39 | NoCount: no.String(), 40 | } 41 | } 42 | 43 | // NewTallyResultFromMap creates a new TallyResult instance from a Option -> Dec map 44 | func NewTallyResultFromMap(results map[VoteOption]math.LegacyDec) TallyResult { 45 | return NewTallyResult( 46 | results[OptionYes].TruncateInt(), 47 | results[OptionAbstain].TruncateInt(), 48 | results[OptionNo].TruncateInt(), 49 | ) 50 | } 51 | 52 | // EmptyTallyResult returns an empty TallyResult. 53 | func EmptyTallyResult() TallyResult { 54 | return NewTallyResult(math.ZeroInt(), math.ZeroInt(), math.ZeroInt()) 55 | } 56 | 57 | // Equals returns if two tally results are equal. 58 | func (tr TallyResult) Equals(comp TallyResult) bool { 59 | return tr.YesCount == comp.YesCount && 60 | tr.AbstainCount == comp.AbstainCount && 61 | tr.NoCount == comp.NoCount 62 | } 63 | -------------------------------------------------------------------------------- /tests/e2e/chain_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | atomone "github.com/atomone-hub/atomone/app" 8 | 9 | "cosmossdk.io/log" 10 | tmrand "github.com/cometbft/cometbft/libs/rand" 11 | 12 | dbm "github.com/cosmos/cosmos-db" 13 | 14 | "github.com/cosmos/cosmos-sdk/client" 15 | "github.com/cosmos/cosmos-sdk/codec" 16 | sdk "github.com/cosmos/cosmos-sdk/types" 17 | "github.com/cosmos/cosmos-sdk/types/module" 18 | ) 19 | 20 | const ( 21 | keyringPassphrase = "testpassphrase" 22 | keyringAppName = "testnet" 23 | ) 24 | 25 | type chain struct { 26 | dataDir string 27 | id string 28 | validators []*validator 29 | accounts []*account //nolint:unused 30 | multiSigAccounts []*multiSigAccount 31 | // initial accounts in genesis 32 | genesisAccounts []*account 33 | genesisVestingAccounts map[string]sdk.AccAddress 34 | 35 | // codecs and chain config 36 | cdc codec.Codec 37 | txConfig client.TxConfig 38 | bm module.BasicManager 39 | } 40 | 41 | func newChain() (*chain, error) { 42 | tmpDir, err := os.MkdirTemp("", "atomone-e2e-testnet-") 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | tempApp := atomone.NewAtomOneApp(log.NewNopLogger(), dbm.NewMemDB(), nil, false, atomone.EmptyAppOptions{}) 48 | 49 | return &chain{ 50 | id: "chain-" + tmrand.Str(6), 51 | dataDir: tmpDir, 52 | cdc: tempApp.AppCodec(), 53 | txConfig: tempApp.GetTxConfig(), 54 | bm: tempApp.BasicModuleManager(), 55 | }, nil 56 | } 57 | 58 | func (c *chain) configDir() string { 59 | return fmt.Sprintf("%s/%s", c.dataDir, c.id) 60 | } 61 | 62 | func (c *chain) createAndInitValidators(count int) error { 63 | for i := 0; i < count; i++ { 64 | node := c.createValidator(i) 65 | 66 | // generate genesis files 67 | if err := node.init(); err != nil { 68 | return err 69 | } 70 | 71 | c.validators = append(c.validators, node) 72 | 73 | // create keys 74 | if err := node.createKey("val"); err != nil { 75 | return err 76 | } 77 | if err := node.createNodeKey(); err != nil { 78 | return err 79 | } 80 | if err := node.createConsensusKey(); err != nil { 81 | return err 82 | } 83 | } 84 | 85 | return nil 86 | } 87 | 88 | func (c *chain) createValidator(index int) *validator { 89 | return &validator{ 90 | chain: c, 91 | index: index, 92 | moniker: fmt.Sprintf("%s-atomone-%d", c.id, index), 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/sim_bench_test.go: -------------------------------------------------------------------------------- 1 | package atomone_test 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | "github.com/cosmos/cosmos-sdk/baseapp" 10 | "github.com/cosmos/cosmos-sdk/server" 11 | simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 12 | simulation2 "github.com/cosmos/cosmos-sdk/types/simulation" 13 | "github.com/cosmos/cosmos-sdk/x/simulation" 14 | simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" 15 | 16 | atomone "github.com/atomone-hub/atomone/app" 17 | ) 18 | 19 | // Profile with: 20 | // /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/AtomOneApp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out 21 | func BenchmarkFullAppSimulation(b *testing.B) { 22 | b.ReportAllocs() 23 | 24 | config := simcli.NewConfigFromFlags() 25 | config.ChainID = AppChainID 26 | 27 | db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "goleveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue) 28 | if err != nil { 29 | b.Fatalf("simulation setup failed: %s", err.Error()) 30 | } 31 | 32 | if skip { 33 | b.Skip("skipping benchmark application simulation") 34 | } 35 | 36 | defer func() { 37 | require.NoError(b, db.Close()) 38 | require.NoError(b, os.RemoveAll(dir)) 39 | }() 40 | 41 | appOptions := make(simtestutil.AppOptionsMap, 0) 42 | appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue 43 | 44 | app := atomone.NewAtomOneApp( 45 | logger, 46 | db, 47 | nil, 48 | true, 49 | appOptions, 50 | interBlockCacheOpt(), 51 | baseapp.SetChainID(AppChainID), 52 | ) 53 | 54 | // Run randomized simulation:w 55 | _, simParams, simErr := simulation.SimulateFromSeed( 56 | b, 57 | os.Stdout, 58 | app.BaseApp, 59 | simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), 60 | simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 61 | simtestutil.SimulationOperations(app, app.AppCodec(), config), 62 | app.ModuleAccountAddrs(), 63 | config, 64 | app.AppCodec(), 65 | ) 66 | 67 | // export state and simParams before the simulation error is checked 68 | if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil { 69 | b.Fatal(err) 70 | } 71 | 72 | if simErr != nil { 73 | b.Fatal(simErr) 74 | } 75 | 76 | if config.Commit { 77 | simtestutil.PrintStats(db) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /x/photon/ante/ante.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | 9 | "github.com/atomone-hub/atomone/x/photon/types" 10 | ) 11 | 12 | var _ sdk.AnteDecorator = ValidateFeeDecorator{} 13 | 14 | type ValidateFeeDecorator struct { 15 | k PhotonKeeper 16 | } 17 | 18 | func NewValidateFeeDecorator(k PhotonKeeper) ValidateFeeDecorator { 19 | return ValidateFeeDecorator{k: k} 20 | } 21 | 22 | // AnteHandle implements the sdk.AnteDecorator interface. 23 | // It returns an error if the tx fee denom is not photon, with some exceptions: 24 | // - tx has no fees or 0 fees. 25 | // - tx messages' type URLs match the `TxFeeExceptions` field of the 26 | // [types.Params]. 27 | func (vfd ValidateFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 28 | feeTx, ok := tx.(sdk.FeeTx) 29 | if !ok { 30 | return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") 31 | } 32 | feeCoins := feeTx.GetFee() 33 | if feeCoins.IsZero() { 34 | // Skip if no fees 35 | return next(ctx, tx, simulate) 36 | } 37 | 38 | if AllowsAnyTxFee(tx, vfd.k.GetParams(ctx).TxFeeExceptions) { 39 | // Skip if tx is declared in TxFeeExceptions (any fee coins are allowed). 40 | return next(ctx, tx, simulate) 41 | } 42 | 43 | if len(feeCoins) > 1 { 44 | return ctx, types.ErrTooManyFeeCoins 45 | } 46 | if feeDenom := feeCoins[0].Denom; feeDenom != types.Denom { 47 | // feeDenom not allowed 48 | return ctx, errorsmod.Wrapf(types.ErrInvalidFeeToken, "fee denom %s not allowed; only fee denom %s is allowed", feeDenom, types.Denom) 49 | } 50 | // feeDenom photon is allowed 51 | return next(ctx, tx, simulate) 52 | } 53 | 54 | // AllowsAnyTxFee returns true if all tx messages type URL are presents in 55 | // txFeeExceptions, or if it starts with a wildcard "*". 56 | func AllowsAnyTxFee(tx sdk.Tx, txFeeExceptions []string) bool { 57 | if len(txFeeExceptions) > 0 && txFeeExceptions[0] == "*" { 58 | // wildcard detected, all tx fees are allowed. 59 | return true 60 | } 61 | var anyTxFeeMsgCount int 62 | for _, msg := range tx.GetMsgs() { 63 | msgTypeURL := sdk.MsgTypeURL(msg) 64 | for _, exception := range txFeeExceptions { 65 | if exception == msgTypeURL { 66 | anyTxFeeMsgCount++ 67 | break 68 | } 69 | } 70 | } 71 | return anyTxFeeMsgCount == len(tx.GetMsgs()) 72 | } 73 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/production.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Description 6 | 7 | Closes: #XXXX 8 | 9 | 11 | 12 | 13 | 14 | --- 15 | 16 | ### Author Checklist 17 | 18 | *All items are required. Please add a note to the item if the item is not applicable and 19 | please add links to any relevant follow up issues.* 20 | 21 | I have... 22 | 23 | * [ ] Included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title 24 | * [ ] Added `!` to the type prefix if API, client, or state breaking change (i.e., requires minor or major version bump) 25 | * [ ] Targeted the correct branch (see [PR Targeting](https://github.com/atomone-hub/atomone/blob/main/CONTRIBUTING.md#pr-targeting)) 26 | * [ ] Provided a link to the relevant issue or specification 27 | * [ ] Followed the guidelines for [building SDK modules](https://github.com/atomone-hub/atomone/blob/main/docs/docs/building-modules) 28 | * [ ] Included the necessary unit and integration [tests](https://github.com/atomone-hub/atomone/blob/main/CONTRIBUTING.md#testing) 29 | * [ ] Added a changelog entry in `.changelog` (for details, see [contributing guidelines](../../CONTRIBUTING.md#changelog)) 30 | * [ ] Included comments for [documenting Go code](https://blog.golang.org/godoc) 31 | * [ ] Updated the relevant documentation or specification 32 | * [ ] Reviewed "Files changed" and left comments if necessary 33 | * [ ] Confirmed all CI checks have passed 34 | 35 | ### Reviewers Checklist 36 | 37 | *All items are required. Please add a note if the item is not applicable and please add 38 | your handle next to the items reviewed if you only reviewed selected items.* 39 | 40 | I have... 41 | 42 | * [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title 43 | * [ ] confirmed `!` in the type prefix if API or client breaking change 44 | * [ ] confirmed all author checklist items have been addressed 45 | * [ ] reviewed state machine logic 46 | * [ ] reviewed API design and naming 47 | * [ ] reviewed documentation is accurate 48 | * [ ] reviewed tests and test coverage 49 | -------------------------------------------------------------------------------- /.github/workflows/release-sims.yml: -------------------------------------------------------------------------------- 1 | name: Release Sims 2 | on: 3 | pull_request: 4 | branches: 5 | - "rc**" 6 | 7 | jobs: 8 | cleanup-runs: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: rokroskar/workflow-run-cleanup-action@master 12 | env: 13 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 14 | if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'" 15 | 16 | build: 17 | runs-on: ubuntu-latest 18 | if: "!contains(github.event.head_commit.message, 'skip-sims')" 19 | steps: 20 | - uses: actions/checkout@v4 21 | - run: | 22 | make build 23 | 24 | newbuild: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/setup-go@v5 28 | with: 29 | go-version-file: go.mod 30 | - name: Install runsim 31 | run: go install github.com/cosmos/tools/cmd/runsim@v1.0.0 32 | - uses: actions/cache@v4 33 | with: 34 | path: ~/go/bin 35 | key: ${{ runner.os }}-go-runsim-binary 36 | 37 | install-runsim: 38 | runs-on: ubuntu-latest 39 | needs: build 40 | steps: 41 | - name: install runsim 42 | run: go install github.com/cosmos/tools/cmd/runsim@v1.0.0 43 | - uses: actions/cache@v4 44 | with: 45 | path: ~/go/bin 46 | key: ${{ runner.os }}-go-runsim-binary 47 | 48 | test-sim-multi-seed-long: 49 | runs-on: ubuntu-latest 50 | needs: [build, install-runsim] 51 | steps: 52 | - uses: actions/checkout@v4 53 | - uses: actions/cache@v4 54 | with: 55 | path: ~/go/bin 56 | key: ${{ runner.os }}-go-runsim-binary 57 | - name: test-sim-multi-seed-long 58 | run: | 59 | make test-sim-multi-seed-long 60 | 61 | test-sim-nondeterminism: 62 | runs-on: ubuntu-latest 63 | needs: newbuild 64 | steps: 65 | - uses: actions/checkout@v4 66 | - uses: actions/setup-go@v5 67 | with: 68 | go-version-file: go.mod 69 | - uses: technote-space/get-diff-action@v6.0.1 70 | with: 71 | PATTERNS: | 72 | **/**.go 73 | go.mod 74 | go.sum 75 | - uses: actions/cache@v4 76 | with: 77 | path: ~/go/bin 78 | key: ${{ runner.os }}-go-runsim-binary 79 | if: "env.GIT_DIFF != ''" 80 | - name: test nondeterminism 81 | run: | 82 | make test-sim-nondeterminism 83 | if: "env.GIT_DIFF != ''" 84 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | tests: false 3 | # timeout for analysis, e.g. 30s, 5m, default is 1m 4 | timeout: 5m 5 | skip-dirs: 6 | - tests/ 7 | skip-files: 8 | - ".*\\.pb\\.go$" 9 | - ".*\\.pb\\.gw\\.go$" 10 | - x/gov/types/v1/wrapper.go 11 | - x/gov/types/v1beta1/wrapper.go 12 | 13 | linters: 14 | disable-all: true 15 | enable: 16 | - dogsled 17 | - errcheck 18 | - gci 19 | - goconst 20 | - gocritic 21 | - gofumpt 22 | - gosec 23 | - gosimple 24 | - govet 25 | - ineffassign 26 | - misspell 27 | - nakedret 28 | - nolintlint 29 | - staticcheck 30 | - stylecheck 31 | - typecheck 32 | - thelper 33 | - unconvert 34 | - unparam 35 | - unused 36 | 37 | issues: 38 | exclude-rules: 39 | - text: "Use of weak random number generator" 40 | linters: 41 | - gosec 42 | - text: "comment on exported var" 43 | linters: 44 | - golint 45 | - text: "don't use an underscore in package name" 46 | linters: 47 | - golint 48 | - text: "ST1003:" 49 | linters: 50 | - stylecheck 51 | # FIXME: Disabled until golangci-lint updates stylecheck with this fix: 52 | # https://github.com/dominikh/go-tools/issues/389 53 | - text: "ST1016:" 54 | linters: 55 | - stylecheck 56 | - path: "migrations" 57 | text: "SA1019:" 58 | linters: 59 | - staticcheck 60 | - linters: 61 | - gosec 62 | text: "G115: integer overflow conversion" 63 | 64 | max-issues-per-linter: 10000 65 | max-same-issues: 10000 66 | 67 | linters-settings: 68 | gci: 69 | custom-order: true 70 | sections: 71 | - standard # Standard section: captures all standard packages. 72 | - default # Default section: contains all imports that could not be matched to another section type. 73 | - blank # blank imports 74 | - dot # dot imports 75 | - prefix(github.com/cometbft/cometbft) # comet 76 | - prefix(github.com/cosmos) # cosmos org 77 | - prefix(cosmossdk.io) # new modules 78 | - prefix(github.com/cosmos/cosmos-sdk) # cosmos sdk 79 | - prefix(github.com/atomone-hub/atomone) # AtomOne 80 | dogsled: 81 | max-blank-identifiers: 3 82 | maligned: 83 | # print struct with more effective memory layout or not, false by default 84 | suggest-new: true 85 | nolintlint: 86 | allow-unused: false 87 | allow-leading-space: true 88 | require-explanation: false 89 | require-specific: false 90 | -------------------------------------------------------------------------------- /proto/atomone/photon/v1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package atomone.photon.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/base/v1beta1/coin.proto"; 6 | import "cosmos_proto/cosmos.proto"; 7 | import "cosmos/msg/v1/msg.proto"; 8 | import "amino/amino.proto"; 9 | import "atomone/photon/v1/photon.proto"; 10 | 11 | option go_package = "github.com/atomone-hub/atomone/x/photon/types"; 12 | 13 | // Msg defines the Msg service. 14 | service Msg { 15 | option (cosmos.msg.v1.service) = true; 16 | 17 | // MintPhoton defines a method to burn atone and mint photons. 18 | rpc MintPhoton(MsgMintPhoton) returns (MsgMintPhotonResponse); 19 | 20 | // UpdateParams defines a governance operation for updating the x/photon 21 | // module parameters. The authority is defined in the keeper. 22 | rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); 23 | } 24 | 25 | // MsgMintPhoton defines an sdk.Msg for burning atone and minting photons. 26 | message MsgMintPhoton { 27 | option (cosmos.msg.v1.signer) = "to_address"; 28 | option (amino.name) = "atomone/photon/v1/MsgMintPhoton"; 29 | 30 | option (gogoproto.equal) = false; 31 | option (gogoproto.goproto_getters) = false; 32 | 33 | string to_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 34 | cosmos.base.v1beta1.Coin amount = 2 35 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 36 | } 37 | 38 | // MsgMintPhotonResponse defines the response structure for executing a 39 | // MsgMintPhoton message. 40 | message MsgMintPhotonResponse { 41 | cosmos.base.v1beta1.Coin minted = 1 [ 42 | (gogoproto.nullable) = false, 43 | (amino.dont_omitempty) = true 44 | ]; 45 | // conversion_rate represents the factor used to convert atone to photon. 46 | string conversion_rate = 2 [ (cosmos_proto.scalar) = "cosmos.Dec" ]; 47 | } 48 | 49 | // MsgUpdateParams is the Msg/UpdateParams request type. 50 | message MsgUpdateParams { 51 | option (cosmos.msg.v1.signer) = "authority"; 52 | option (amino.name) = "atomone/x/photon/v1/MsgUpdateParams"; 53 | 54 | // authority is the address that controls the module (defaults to x/gov unless 55 | // overwritten). 56 | string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 57 | 58 | // params defines the x/gov parameters to update. 59 | // 60 | // NOTE: All parameters must be supplied. 61 | Params params = 2 62 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 63 | } 64 | 65 | // MsgUpdateParamsResponse defines the response structure for executing a 66 | // MsgUpdateParams message. 67 | message MsgUpdateParamsResponse {} 68 | -------------------------------------------------------------------------------- /x/gov/types/v1beta1/genesis.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "fmt" 5 | 6 | "cosmossdk.io/math" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec/types" 9 | ) 10 | 11 | // NewGenesisState creates a new genesis state for the governance module 12 | func NewGenesisState(startingProposalID uint64, dp DepositParams, vp VotingParams, tp TallyParams) *GenesisState { 13 | return &GenesisState{ 14 | StartingProposalId: startingProposalID, 15 | DepositParams: dp, 16 | VotingParams: vp, 17 | TallyParams: tp, 18 | } 19 | } 20 | 21 | // DefaultGenesisState defines the default governance genesis state 22 | func DefaultGenesisState() *GenesisState { 23 | return NewGenesisState( 24 | DefaultStartingProposalID, 25 | DefaultDepositParams(), 26 | DefaultVotingParams(), 27 | DefaultTallyParams(), 28 | ) 29 | } 30 | 31 | // Equal returns true if the GenesisStates are equal 32 | func (data GenesisState) Equal(other GenesisState) bool { 33 | return data.StartingProposalId == other.StartingProposalId && 34 | data.Deposits.Equal(other.Deposits) && 35 | data.Votes.Equal(other.Votes) && 36 | data.Proposals.Equal(other.Proposals) && 37 | data.DepositParams.Equal(other.DepositParams) && 38 | data.TallyParams.Equal(other.TallyParams) && 39 | data.VotingParams.Equal(other.VotingParams) 40 | } 41 | 42 | // Empty returns true if a GenesisState is empty 43 | func (data GenesisState) Empty() bool { 44 | return data.Equal(GenesisState{}) 45 | } 46 | 47 | // ValidateGenesis checks if parameters are within valid ranges 48 | func ValidateGenesis(data *GenesisState) error { 49 | threshold := data.TallyParams.Threshold 50 | if threshold.IsNegative() || threshold.GT(math.LegacyOneDec()) { 51 | return fmt.Errorf("governance vote threshold should be positive and less or equal to one, is %s", 52 | threshold.String()) 53 | } 54 | 55 | veto := data.TallyParams.VetoThreshold 56 | if veto.IsNegative() || veto.GT(math.LegacyOneDec()) { 57 | return fmt.Errorf("governance vote veto threshold should be positive and less or equal to one, is %s", 58 | veto.String()) 59 | } 60 | 61 | if !data.DepositParams.MinDeposit.IsValid() { 62 | return fmt.Errorf("governance deposit amount must be a valid sdk.Coins amount, is %s", 63 | data.DepositParams.MinDeposit.String()) 64 | } 65 | 66 | return nil 67 | } 68 | 69 | var _ types.UnpackInterfacesMessage = GenesisState{} 70 | 71 | // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 72 | func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { 73 | for _, p := range data.Proposals { 74 | err := p.UnpackInterfaces(unpacker) 75 | if err != nil { 76 | return err 77 | } 78 | } 79 | return nil 80 | } 81 | --------------------------------------------------------------------------------