Skip to content

Commit

Permalink
#ntrn-365 credits contract (#5)
Browse files Browse the repository at this point in the history
* #ntrn-365 feat: add basic structure for credits contract

* fix lint

* feat: fill missing methods

* feat: implement mint and instantiate cw20 contract

* fix instantiation and more adjustments

* feat: add queries to credits contract

* cleanup

* add test script for credits

* add burn_all message

* fix script

* add more stuff to script

* add ability to update contract addresses later

* add instantiate tests

* implement add_vesting

* remove sale_address

* add vesting

* add test for compute withdrawable amount

* add query allocation

* add mint tests

* test mint

* tests for add_vesting

* add big test about vesting

* add more test

* tmp

* add tests, fix comments and methods

* add when_withdrawable, add test for update config

* add tests for transfer

* finish with tests

* Add burn_from

* remove todos

* fix withdraw after burn rewards

* add balanceAtHeight impl

* add comments

* add comments

* cleanup, change readme

* refactor tests - withdraw

* add tests to withdraw

* add more descriptive comment

* removed unneeded transfer_from, increase/decrease_allowance

* add total_supply_at_height query

* query_vested_amount

* start writing documentation

* add more comments

* more docs

* more comments

* review fixes

* remove dao_address from instantiate msg

* fix more comments

* small fix

* move credits tests to testing module

* fix more pr comments

* more pr fixes

* transparent errors

* rename ucntrn -> cntrn

* rename again

* commit schema for credits contract

* remove config update mechanism since we have all addresses fix on init

* update credits contract after changing cw20base to 0.13.4 version

* cleanup reviews

* fix comments

* fix clippy warnings

* fix token names in comments

---------

Co-authored-by: Murad Karammaev <muradkarammaev@gmail.com>
  • Loading branch information
NeverHappened and foxpy authored Mar 3, 2023
1 parent e18dd7d commit d7be169
Show file tree
Hide file tree
Showing 31 changed files with 3,021 additions and 81 deletions.
230 changes: 153 additions & 77 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions contracts/credits/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[alias]
wasm = "build --release --lib --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --example credits_schema"
15 changes: 15 additions & 0 deletions contracts/credits/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Build results
/target

# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327)
.cargo-ok

# Text file backups
**/*.rs.bk

# macOS
.DS_Store

# IDEs
*.iml
.idea
56 changes: 56 additions & 0 deletions contracts/credits/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[package]
name = "credits"
version = "0.1.0"
authors = ["nhpd <dmitry.klpv@gmail.com>"]
edition = "2021"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[profile.release]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1
panic = 'abort'
incremental = false
overflow-checks = true

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[package.metadata.scripts]
optimize = """docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.12.10
"""

[dependencies]
cosmwasm-schema = "1.0.0"
cosmwasm-std = "1.0.0"
cosmwasm-storage = "1.0.0"
cw-storage-plus = { version = "0.13" }
cw2 = "0.13"
cw20 = { version = "0.13" }
cw20-base = { git = "https://github.com/neutron-org/cw-plus_balances-snapshots", rev = "bfe7471ae59a0aa68155841a741d428030183b1a", features = ["library"] }
cw-utils = "0.13.4"
schemars = "0.8.10"
serde = { version = "1.0.145", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.31" }

[dev-dependencies]
cw-multi-test = "0.13"
5 changes: 5 additions & 0 deletions contracts/credits/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Credits contract

This is the cw20 like contract that mints cNTRN tokens and holds vested untrn tokens in 1:1 proportion.

Mostly used by airdrop contract to distribute/vest airdropped funds.
41 changes: 41 additions & 0 deletions contracts/credits/examples/credits_schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::env::current_dir;
use std::fs::create_dir_all;

use cosmwasm_schema::{export_schema, remove_schemas, schema_for};
use cw20::{
AllAccountsResponse, AllAllowancesResponse, AllowanceResponse, BalanceResponse, MinterResponse,
TokenInfoResponse,
};

use credits::msg::{
ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, TotalSupplyResponse, VestedAmountResponse,
WithdrawableAmountResponse,
};
use credits::state::{Allocation, Config, Schedule};

fn main() {
let mut out_dir = current_dir().unwrap();
out_dir.push("schema");
create_dir_all(&out_dir).unwrap();
remove_schemas(&out_dir).unwrap();

export_schema(&schema_for!(InstantiateMsg), &out_dir);
export_schema(&schema_for!(ExecuteMsg), &out_dir);
export_schema(&schema_for!(QueryMsg), &out_dir);
export_schema(&schema_for!(MigrateMsg), &out_dir);

export_schema(&schema_for!(Config), &out_dir);
export_schema(&schema_for!(Allocation), &out_dir);
export_schema(&schema_for!(Schedule), &out_dir);

export_schema(&schema_for!(TotalSupplyResponse), &out_dir);
export_schema(&schema_for!(WithdrawableAmountResponse), &out_dir);
export_schema(&schema_for!(VestedAmountResponse), &out_dir);

export_schema(&schema_for!(BalanceResponse), &out_dir);
export_schema(&schema_for!(TokenInfoResponse), &out_dir);
export_schema(&schema_for!(MinterResponse), &out_dir);
export_schema(&schema_for!(AllowanceResponse), &out_dir);
export_schema(&schema_for!(AllAllowancesResponse), &out_dir);
export_schema(&schema_for!(AllAccountsResponse), &out_dir);
}
16 changes: 16 additions & 0 deletions contracts/credits/schema/all_accounts_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AllAccountsResponse",
"type": "object",
"required": [
"accounts"
],
"properties": {
"accounts": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
99 changes: 99 additions & 0 deletions contracts/credits/schema/all_allowances_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AllAllowancesResponse",
"type": "object",
"required": [
"allowances"
],
"properties": {
"allowances": {
"type": "array",
"items": {
"$ref": "#/definitions/AllowanceInfo"
}
}
},
"definitions": {
"AllowanceInfo": {
"type": "object",
"required": [
"allowance",
"expires",
"spender"
],
"properties": {
"allowance": {
"$ref": "#/definitions/Uint128"
},
"expires": {
"$ref": "#/definitions/Expiration"
},
"spender": {
"type": "string"
}
}
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"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"
}
}
}
70 changes: 70 additions & 0 deletions contracts/credits/schema/allocation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Allocation",
"type": "object",
"required": [
"allocated_amount",
"schedule",
"withdrawn_amount"
],
"properties": {
"allocated_amount": {
"description": "Total allocated amount that can be withdrawn",
"allOf": [
{
"$ref": "#/definitions/Uint128"
}
]
},
"schedule": {
"description": "Vesting schedule settings for this allocation",
"allOf": [
{
"$ref": "#/definitions/Schedule"
}
]
},
"withdrawn_amount": {
"description": "Amount that has already been withdrawn from account (Does not include reward withdraws)",
"allOf": [
{
"$ref": "#/definitions/Uint128"
}
]
}
},
"definitions": {
"Schedule": {
"type": "object",
"required": [
"cliff",
"duration",
"start_time"
],
"properties": {
"cliff": {
"description": "Specified in seconds. Tokens start to get unlocked at `start_time + cliff` time.",
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"duration": {
"description": "Duration of the vesting/unlocking process. At time `start_time + duration`, 100% of the tokens are vested/unlocked in full.",
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"start_time": {
"description": "Timestamp in UNIX seconds when vesting/unlocking starts",
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
},
"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"
}
}
}
81 changes: 81 additions & 0 deletions contracts/credits/schema/allowance_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AllowanceResponse",
"type": "object",
"required": [
"allowance",
"expires"
],
"properties": {
"allowance": {
"$ref": "#/definitions/Uint128"
},
"expires": {
"$ref": "#/definitions/Expiration"
}
},
"definitions": {
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"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"
}
}
}
Loading

0 comments on commit d7be169

Please sign in to comment.