diff --git a/.github/workflows/babylon_vault.yml b/.github/workflows/babylon_vault.yml new file mode 100644 index 000000000..617cd7100 --- /dev/null +++ b/.github/workflows/babylon_vault.yml @@ -0,0 +1,26 @@ +name: Babylon Vault + +on: + pull_request: + branches: + - main + paths: + - 'smart-contracts/contracts/babylon-vault/Cargo.toml' + - 'smart-contracts/contracts/babylon-vault/**.rs' + - '.github/workflows/rust_basic.yml' + - '.github/workflows/babylon_vault.yml' + push: + branches: + - main + paths: + - 'smart-contracts/contracts/babylon-vault/Cargo.toml' + - 'smart-contracts/contracts/babylon-vault/**.rs' + - '.github/workflows/rust_basic.yml' + - '.github/workflows/babylon_vault.yml' + workflow_dispatch: + +jobs: + unit-test: + uses: ./.github/workflows/rust_basic.yml + with: + target: 'contracts/babylon-vault' \ No newline at end of file diff --git a/scripts/git/pre-commit b/scripts/git/pre-commit index 4e9a9b52f..e57932db2 100644 --- a/scripts/git/pre-commit +++ b/scripts/git/pre-commit @@ -44,3 +44,4 @@ update_schemas_and_formatting token-burner update_schemas_and_formatting cl-vault update_schemas_and_formatting merkle-incentives update_schemas_and_formatting range-middleware +update_schemas_and_formatting babylon-vault diff --git a/smart-contracts/Cargo.lock b/smart-contracts/Cargo.lock index d0bdec7f8..2816a2f67 100644 --- a/smart-contracts/Cargo.lock +++ b/smart-contracts/Cargo.lock @@ -1398,6 +1398,17 @@ dependencies = [ "tower-service", ] +[[package]] +name = "babylon-vault" +version = "0.0.1" +dependencies = [ + "cosmwasm-schema 1.5.4", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "thiserror", +] + [[package]] name = "backtrace" version = "0.3.69" diff --git a/smart-contracts/Cargo.toml b/smart-contracts/Cargo.toml index 270f37c13..8c6c1b897 100644 --- a/smart-contracts/Cargo.toml +++ b/smart-contracts/Cargo.toml @@ -17,6 +17,7 @@ members = [ "contracts/dex-router-osmosis", "contracts/lst-dex-adapter-osmosis", "contracts/lst-adapter-osmosis", + "contracts/babylon-vault", ] [workspace.dependencies] diff --git a/smart-contracts/contracts/babylon-vault/Cargo.toml b/smart-contracts/contracts/babylon-vault/Cargo.toml new file mode 100644 index 000000000..11290aad4 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/Cargo.toml @@ -0,0 +1,31 @@ +[package] +authors = ["Quasar"] +edition = "2021" +name = "babylon-vault" +version = "0.0.1" +readme = "" +repository = "https://github.com/quasar-finance/quasar" +homepage = "https://quasar.fi" +documentation = "" +license = "MPL-2.0" +description = "A vault for babylon lsts" +keywords = ["cosmwasm", "lst", "btc"] + +exclude = [ + "babylon_vault.wasm", + "hash.txt", +] + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = [] +library = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-storage-plus = { workspace = true } +thiserror = { workspace = true } +cw2 = { workspace = true } diff --git a/smart-contracts/contracts/babylon-vault/examples/schema.rs b/smart-contracts/contracts/babylon-vault/examples/schema.rs new file mode 100644 index 000000000..2d9623f4f --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/examples/schema.rs @@ -0,0 +1,10 @@ +use babylon_vault::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use cosmwasm_schema::write_api; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + query: QueryMsg, + execute: ExecuteMsg, + } +} diff --git a/smart-contracts/contracts/babylon-vault/schema/babylon-vault.json b/smart-contracts/contracts/babylon-vault/schema/babylon-vault.json new file mode 100644 index 000000000..cb0a68945 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/babylon-vault.json @@ -0,0 +1,196 @@ +{ + "contract_name": "babylon-vault", + "contract_version": "0.0.1", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "deposit" + ], + "properties": { + "deposit": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw" + ], + "properties": { + "withdraw": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim" + ], + "properties": { + "claim": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "register_lst" + ], + "properties": { + "register_lst": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "pending" + ], + "properties": { + "pending": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claimable" + ], + "properties": { + "claimable": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "balance_in_underlying" + ], + "properties": { + "balance_in_underlying": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "balance_in_underlying": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint128", + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "claimable": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint128", + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "pending": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_Claim", + "type": "array", + "items": { + "$ref": "#/definitions/Claim" + }, + "definitions": { + "Claim": { + "type": "object", + "required": [ + "amount", + "expiration" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "expiration": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + } + } +} diff --git a/smart-contracts/contracts/babylon-vault/schema/raw/execute.json b/smart-contracts/contracts/babylon-vault/schema/raw/execute.json new file mode 100644 index 000000000..b978c2b19 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/raw/execute.json @@ -0,0 +1,66 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "deposit" + ], + "properties": { + "deposit": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw" + ], + "properties": { + "withdraw": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim" + ], + "properties": { + "claim": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "register_lst" + ], + "properties": { + "register_lst": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/smart-contracts/contracts/babylon-vault/schema/raw/instantiate.json b/smart-contracts/contracts/babylon-vault/schema/raw/instantiate.json new file mode 100644 index 000000000..1352613d5 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/raw/instantiate.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "additionalProperties": false +} diff --git a/smart-contracts/contracts/babylon-vault/schema/raw/query.json b/smart-contracts/contracts/babylon-vault/schema/raw/query.json new file mode 100644 index 000000000..630717c77 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/raw/query.json @@ -0,0 +1,61 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "pending" + ], + "properties": { + "pending": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claimable" + ], + "properties": { + "claimable": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "balance_in_underlying" + ], + "properties": { + "balance_in_underlying": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/smart-contracts/contracts/babylon-vault/schema/raw/response_to_balance_in_underlying.json b/smart-contracts/contracts/babylon-vault/schema/raw/response_to_balance_in_underlying.json new file mode 100644 index 000000000..25b73e8f2 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/raw/response_to_balance_in_underlying.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint128", + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" +} diff --git a/smart-contracts/contracts/babylon-vault/schema/raw/response_to_claimable.json b/smart-contracts/contracts/babylon-vault/schema/raw/response_to_claimable.json new file mode 100644 index 000000000..25b73e8f2 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/raw/response_to_claimable.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint128", + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" +} diff --git a/smart-contracts/contracts/babylon-vault/schema/raw/response_to_pending.json b/smart-contracts/contracts/babylon-vault/schema/raw/response_to_pending.json new file mode 100644 index 000000000..e31aaea7b --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/schema/raw/response_to_pending.json @@ -0,0 +1,42 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_Claim", + "type": "array", + "items": { + "$ref": "#/definitions/Claim" + }, + "definitions": { + "Claim": { + "type": "object", + "required": [ + "amount", + "expiration" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "expiration": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/smart-contracts/contracts/babylon-vault/src/contract.rs b/smart-contracts/contracts/babylon-vault/src/contract.rs new file mode 100644 index 000000000..83a0e3b87 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/src/contract.rs @@ -0,0 +1,40 @@ +use crate::error::VaultError; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response}; +use cw2::set_contract_version; + +const CONTRACT_NAME: &str = "quasar:babylon-vault"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub type VaultResult = Result; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: InstantiateMsg, +) -> VaultResult { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: ExecuteMsg) -> VaultResult { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> VaultResult { + Ok(Binary::default()) +} + +#[cfg(test)] +mod tests { + #[test] + fn dummy_test() { + assert!(true); + } +} diff --git a/smart-contracts/contracts/babylon-vault/src/error.rs b/smart-contracts/contracts/babylon-vault/src/error.rs new file mode 100644 index 000000000..fde081039 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/src/error.rs @@ -0,0 +1,8 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum VaultError { + #[error("{0}")] + Std(#[from] StdError), +} diff --git a/smart-contracts/contracts/babylon-vault/src/lib.rs b/smart-contracts/contracts/babylon-vault/src/lib.rs new file mode 100644 index 000000000..a0cd84f22 --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/src/lib.rs @@ -0,0 +1,5 @@ +pub mod contract; +mod error; +pub mod msg; + +pub use crate::error::VaultError; diff --git a/smart-contracts/contracts/babylon-vault/src/msg.rs b/smart-contracts/contracts/babylon-vault/src/msg.rs new file mode 100644 index 000000000..72bbb479d --- /dev/null +++ b/smart-contracts/contracts/babylon-vault/src/msg.rs @@ -0,0 +1,32 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{Timestamp, Uint128}; + +#[cw_serde] +pub struct InstantiateMsg {} + +#[cw_serde] +pub enum ExecuteMsg { + // permission-less methods + Deposit {}, + Withdraw {}, + Claim {}, + // owner methods + RegisterLst { denom: String }, +} + +#[cw_serde] +pub struct Claim { + pub amount: Uint128, + pub expiration: Timestamp, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(Vec)] + Pending { address: String }, + #[returns(Uint128)] + Claimable { address: String }, + #[returns(Uint128)] + BalanceInUnderlying {}, +}