From d3f13ec4ce115a1b438500e2d1b998bf0b4daa38 Mon Sep 17 00:00:00 2001 From: Sergey Ratiashvili Date: Wed, 1 Mar 2023 16:51:20 +0100 Subject: [PATCH] fix: clippy --- Cargo.lock | 48 - contracts/airdrop/.cargo/config | 4 - contracts/airdrop/Cargo.toml | 45 - contracts/airdrop/README.md | 76 - contracts/airdrop/examples/airdrop_schema.rs | 25 - contracts/airdrop/schema/claim_response.json | 13 - contracts/airdrop/schema/config.json | 71 - contracts/airdrop/schema/execute_msg.json | 206 - contracts/airdrop/schema/instantiate_msg.json | 42 - contracts/airdrop/schema/migrate_msg.json | 5 - contracts/airdrop/schema/query_msg.json | 70 - contracts/airdrop/schema/state.json | 42 - contracts/airdrop/src/contract.rs | 629 --- contracts/airdrop/src/crypto.rs | 49 - contracts/airdrop/src/lib.rs | 3 - contracts/airdrop/src/state.rs | 10 - contracts/airdrop/tests/integration.rs | 1438 ------ contracts/auction/Cargo.toml | 1 - contracts/auction/tests/integration.rs | 3045 ------------- contracts/lockdrop/Cargo.toml | 1 - contracts/lockdrop/src/contract.rs | 16 +- contracts/lockdrop/src/migration.rs | 4 +- contracts/lockdrop/src/mock_querier.rs | 8 +- contracts/lockdrop/src/testing.rs | 2 +- contracts/lockdrop/tests/integration.rs | 3952 ----------------- packages/astroport_periphery/src/airdrop.rs | 16 +- packages/astroport_periphery/src/auction.rs | 22 +- packages/astroport_periphery/src/lockdrop.rs | 28 +- .../astroport_periphery/src/simple_airdrop.rs | 18 +- 29 files changed, 56 insertions(+), 9833 deletions(-) delete mode 100644 contracts/airdrop/.cargo/config delete mode 100644 contracts/airdrop/Cargo.toml delete mode 100644 contracts/airdrop/README.md delete mode 100644 contracts/airdrop/examples/airdrop_schema.rs delete mode 100644 contracts/airdrop/schema/claim_response.json delete mode 100644 contracts/airdrop/schema/config.json delete mode 100644 contracts/airdrop/schema/execute_msg.json delete mode 100644 contracts/airdrop/schema/instantiate_msg.json delete mode 100644 contracts/airdrop/schema/migrate_msg.json delete mode 100644 contracts/airdrop/schema/query_msg.json delete mode 100644 contracts/airdrop/schema/state.json delete mode 100644 contracts/airdrop/src/contract.rs delete mode 100644 contracts/airdrop/src/crypto.rs delete mode 100644 contracts/airdrop/src/lib.rs delete mode 100644 contracts/airdrop/src/state.rs delete mode 100644 contracts/airdrop/tests/integration.rs delete mode 100644 contracts/auction/tests/integration.rs delete mode 100644 contracts/lockdrop/tests/integration.rs diff --git a/Cargo.lock b/Cargo.lock index eedf761f..7e5a2c5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,33 +21,11 @@ dependencies = [ "uint", ] -[[package]] -name = "astroport-airdrop" -version = "1.0.0" -dependencies = [ - "astroport", - "astroport-auction", - "astroport-pair", - "astroport-periphery", - "astroport-token", - "cosmwasm-schema", - "cosmwasm-std 1.0.0", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "cw20 0.13.4", - "hex", - "schemars", - "serde", - "sha3", -] - [[package]] name = "astroport-auction" version = "1.0.0" dependencies = [ "astroport", - "astroport-airdrop", "astroport-factory", "astroport-generator", "astroport-lockdrop", @@ -133,7 +111,6 @@ name = "astroport-lockdrop" version = "1.2.0" dependencies = [ "astroport", - "astroport-airdrop", "astroport-auction", "astroport-factory", "astroport-generator", @@ -329,16 +306,9 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding", "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "byteorder" version = "1.4.3" @@ -1023,12 +993,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "keccak" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" - [[package]] name = "libc" version = "0.2.126" @@ -1280,18 +1244,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer", - "digest", - "keccak", - "opaque-debug", -] - [[package]] name = "signature" version = "1.3.2" diff --git a/contracts/airdrop/.cargo/config b/contracts/airdrop/.cargo/config deleted file mode 100644 index 470a955d..00000000 --- a/contracts/airdrop/.cargo/config +++ /dev/null @@ -1,4 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -unit-test = "test --lib" -schema = "run --example airdrop_schema" diff --git a/contracts/airdrop/Cargo.toml b/contracts/airdrop/Cargo.toml deleted file mode 100644 index 27ad98c8..00000000 --- a/contracts/airdrop/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "astroport-airdrop" -version = "1.0.0" -authors = ["_astromartian"] -edition = "2021" -description = "Contract to facilitate ASTRO Token airdrop" - - -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"] - -[features] -# for more explicit tests, cargo test --features=backtraces -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all instantiate/execute/query exports -library = [] - -[dependencies] -cw2 = { version = "0.13" } -cw20 = "0.13" -astroport-periphery = { path = "../../packages/astroport_periphery" } -cosmwasm-std = { version = "1.0" } -cw-storage-plus = { version = "0.13" } -serde = { version = "1.0.127", default-features = false, features = ["derive"] } -schemars = "0.8" -astroport = { git = "https://github.com/astroport-fi/astroport-core.git", branch="main" } - -hex = "0.4.3" -sha3 = "0.9.1" - -[dev-dependencies] -cosmwasm-schema = { version = "1.0" } -cw-multi-test = "0.13" -astroport-token = { git = "https://github.com/astroport-fi/astroport-core.git", branch="main" } -astroport = { git = "https://github.com/astroport-fi/astroport-core.git", branch="main" } -astroport-auction = { path = "../auction" } -astroport-pair = { git = "https://github.com/astroport-fi/astroport-core.git", branch="main" } \ No newline at end of file diff --git a/contracts/airdrop/README.md b/contracts/airdrop/README.md deleted file mode 100644 index 7c47ed2b..00000000 --- a/contracts/airdrop/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# Airdrop - -The Airdrop contract is for ASTRO tokens airdrop claim during the intital protocol launch. - -## Contract Design - -### Handle Messages - -| Message | Description | -| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `ExecuteMsg::Claim` | Executes an airdrop claim for Users. | -| `ExecuteMsg::DelegateAstroToBootstrapAuction` | This function facilitates ASTRO tokens delegation to the Bootstrap auction contract after airdrop is claimed by the user during the bootstrap auction phase. Delegated ASTRO tokens are added to the user's position in the bootstrap auction contract | -| `ExecuteMsg::EnableClaims` | Executed by the Bootstrap auction contract when liquidity is added to the ASTRO-UST pool. Enables ASTRO withdrawals by the airdrop recipients. | -| `ExecuteMsg::WithdrawAirdropReward` | Facilitates ASTRO withdrawal for airdrop recipients once claim withdrawals are allowed | -| `ExecuteMsg::TransferUnclaimedTokens` | Admin function. Transfers unclaimed ASTRO tokens available with the contract to the recipient address once the claim window is over | -| `ExecuteMsg::UpdateConfig` | Admin function to update any of the configuration parameters. | - -- Before the completion of LP bootstrap via auction phase, airdrop claims create user position's within the contract via which users can choose how many ASTRO tokens they want to provide for the LP bootstrap via auction, and withdraw the remaining ASTRO post the completion of LP bootstrap via auction phase - -- Post the completion of LP bootstrap via auction phase, any airdrop claim by the user transfers the user's max ASTRO airdrop amount to the user's wallet. - -### Query Messages - -| Message | Description | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------- | -| `QueryMsg::Config` | Returns the config info | -| `QueryMsg::State` | Returns the contract's state info | -| `QueryMsg::HasUserClaimed` | Returns a boolean value indicating if the corresponding address (terra / evm) have yet claimed their airdrop or not | -| `QueryMsg::UserInfo` | Returns user's airdrop claim state (total airdrop size and ASTRO delegated balances) | - -## How to Guide :: Get merkle proofs - -### Create distribution lists for terra and evm users - -claimees_data.json - -``` -{[ { address: 'terra1k0jntykt7e4g3y88ltc60czgjuqdy4c9ax8tx2', - amount: '43454523323' - }, - { address: 'terra1xzlgeyuuyqje79ma6vllregprkmgwgavjx2h6m', - amount: '1343252443' - } -]} -``` - -### Get proof with user input - -``` - import {Terra_Merkle_Tree} from "./helpers/terra_merkle_tree.js"; - - const terra_merkle_tree = new Terra_Merkle_Tree(terra_claimees_data); - const terra_tree_root = terra_merkle_tree.getMerkleRoot(); - - let merkle_proof_for_terra_user_ = terra_merkle_tree.getMerkleProof({ "address":"terra1k0jntykt7e4g3y88ltc60czgjuqdy4c9ax8tx2", - "amount": (43454523323).toString() - } ); - - console.log("Terra Merkle Root ", terra_tree_root) - console.log("Terra Merkle Proof ", merkle_proof_for_terra_user_) - console.log("Verify Terra Merkle Proof ", terra_merkle_tree.verify({ "address":"terra1k0jntykt7e4g3y88ltc60czgjuqdy4c9ax8tx2", - "amount": (43454523323).toString() - }) ) - -``` - -## Build schema and run unit-tests - -``` -cargo schema -cargo test -``` - -## License - -TBD diff --git a/contracts/airdrop/examples/airdrop_schema.rs b/contracts/airdrop/examples/airdrop_schema.rs deleted file mode 100644 index d9b719d1..00000000 --- a/contracts/airdrop/examples/airdrop_schema.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::env::current_dir; -use std::fs::create_dir_all; - -use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; - -use astroport_periphery::airdrop::{ - ClaimResponse, Config, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, State, -}; - -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!(ClaimResponse), &out_dir); - - export_schema(&schema_for!(Config), &out_dir); - export_schema(&schema_for!(State), &out_dir); -} diff --git a/contracts/airdrop/schema/claim_response.json b/contracts/airdrop/schema/claim_response.json deleted file mode 100644 index cd29005d..00000000 --- a/contracts/airdrop/schema/claim_response.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ClaimResponse", - "type": "object", - "required": [ - "is_claimed" - ], - "properties": { - "is_claimed": { - "type": "boolean" - } - } -} diff --git a/contracts/airdrop/schema/config.json b/contracts/airdrop/schema/config.json deleted file mode 100644 index 02e7d449..00000000 --- a/contracts/airdrop/schema/config.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Config", - "type": "object", - "required": [ - "are_claims_enabled", - "astro_token_address", - "from_timestamp", - "merkle_roots", - "owner", - "to_timestamp" - ], - "properties": { - "are_claims_enabled": { - "description": "Boolean value indicating if the users can withdraw their ASTRO airdrop tokens or not This value is updated in the same Tx in which Liquidity is added to the LP Pool", - "type": "boolean" - }, - "astro_token_address": { - "description": "ASTRO token address", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "auction_contract_address": { - "description": "Bootstrap auction contract address", - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] - }, - "from_timestamp": { - "description": "Timestamp since which ASTRO airdrops can be delegated to bootstrap auction contract", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "merkle_roots": { - "description": "Merkle roots used to verify is a terra user is eligible for the airdrop", - "type": "array", - "items": { - "type": "string" - } - }, - "owner": { - "description": "Account who can update config", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "to_timestamp": { - "description": "Timestamp to which ASTRO airdrops can be claimed", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - } - } -} diff --git a/contracts/airdrop/schema/execute_msg.json b/contracts/airdrop/schema/execute_msg.json deleted file mode 100644 index 29b9bebb..00000000 --- a/contracts/airdrop/schema/execute_msg.json +++ /dev/null @@ -1,206 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecuteMsg", - "oneOf": [ - { - "type": "object", - "required": [ - "receive" - ], - "properties": { - "receive": { - "$ref": "#/definitions/Cw20ReceiveMsg" - } - }, - "additionalProperties": false - }, - { - "description": "Admin function to update the configuration parameters", - "type": "object", - "required": [ - "update_config" - ], - "properties": { - "update_config": { - "type": "object", - "properties": { - "auction_contract_address": { - "type": [ - "string", - "null" - ] - }, - "from_timestamp": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "merkle_roots": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "owner": { - "type": [ - "string", - "null" - ] - }, - "to_timestamp": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - } - } - } - }, - "additionalProperties": false - }, - { - "description": "Called by the bootstrap auction contract when liquidity is added to the ASTRO-UST Pool to enable ASTRO withdrawals by users", - "type": "object", - "required": [ - "enable_claims" - ], - "properties": { - "enable_claims": { - "type": "object" - } - }, - "additionalProperties": false - }, - { - "description": "Allows Terra users to claim their ASTRO Airdrop", - "type": "object", - "required": [ - "claim" - ], - "properties": { - "claim": { - "type": "object", - "required": [ - "claim_amount", - "merkle_proof", - "root_index" - ], - "properties": { - "claim_amount": { - "$ref": "#/definitions/Uint128" - }, - "merkle_proof": { - "type": "array", - "items": { - "type": "string" - } - }, - "root_index": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - } - }, - "additionalProperties": false - }, - { - "description": "Allows users to delegate their ASTRO tokens to the LP Bootstrap auction contract", - "type": "object", - "required": [ - "delegate_astro_to_bootstrap_auction" - ], - "properties": { - "delegate_astro_to_bootstrap_auction": { - "type": "object", - "required": [ - "amount_to_delegate" - ], - "properties": { - "amount_to_delegate": { - "$ref": "#/definitions/Uint128" - } - } - } - }, - "additionalProperties": false - }, - { - "description": "Allows users to withdraw their ASTRO tokens", - "type": "object", - "required": [ - "withdraw_airdrop_reward" - ], - "properties": { - "withdraw_airdrop_reward": { - "type": "object" - } - }, - "additionalProperties": false - }, - { - "description": "Admin function to facilitate transfer of the unclaimed ASTRO Tokens", - "type": "object", - "required": [ - "transfer_unclaimed_tokens" - ], - "properties": { - "transfer_unclaimed_tokens": { - "type": "object", - "required": [ - "amount", - "recipient" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" - }, - "recipient": { - "type": "string" - } - } - } - }, - "additionalProperties": false - } - ], - "definitions": { - "Binary": { - "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec", - "type": "string" - }, - "Cw20ReceiveMsg": { - "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", - "type": "object", - "required": [ - "amount", - "msg", - "sender" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" - }, - "msg": { - "$ref": "#/definitions/Binary" - }, - "sender": { - "type": "string" - } - } - }, - "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/contracts/airdrop/schema/instantiate_msg.json b/contracts/airdrop/schema/instantiate_msg.json deleted file mode 100644 index a7bab727..00000000 --- a/contracts/airdrop/schema/instantiate_msg.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InstantiateMsg", - "type": "object", - "required": [ - "astro_token_address", - "to_timestamp" - ], - "properties": { - "astro_token_address": { - "type": "string" - }, - "from_timestamp": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "merkle_roots": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "owner": { - "type": [ - "string", - "null" - ] - }, - "to_timestamp": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - } -} diff --git a/contracts/airdrop/schema/migrate_msg.json b/contracts/airdrop/schema/migrate_msg.json deleted file mode 100644 index 87b18ea7..00000000 --- a/contracts/airdrop/schema/migrate_msg.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MigrateMsg", - "type": "object" -} diff --git a/contracts/airdrop/schema/query_msg.json b/contracts/airdrop/schema/query_msg.json deleted file mode 100644 index 913cc587..00000000 --- a/contracts/airdrop/schema/query_msg.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryMsg", - "oneOf": [ - { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "type": "object" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "state" - ], - "properties": { - "state": { - "type": "object" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "user_info" - ], - "properties": { - "user_info": { - "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "has_user_claimed" - ], - "properties": { - "has_user_claimed": { - "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "type": "string" - } - } - } - }, - "additionalProperties": false - } - ] -} diff --git a/contracts/airdrop/schema/state.json b/contracts/airdrop/schema/state.json deleted file mode 100644 index ea43bf90..00000000 --- a/contracts/airdrop/schema/state.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "State", - "type": "object", - "required": [ - "total_airdrop_size", - "total_delegated_amount", - "unclaimed_tokens" - ], - "properties": { - "total_airdrop_size": { - "description": "Total ASTRO issuance used as airdrop incentives", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "total_delegated_amount": { - "description": "Total ASTRO tokens that have been delegated to the bootstrap auction pool", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "unclaimed_tokens": { - "description": "Total ASTRO tokens that are yet to be claimed by the users", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "definitions": { - "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/contracts/airdrop/src/contract.rs b/contracts/airdrop/src/contract.rs deleted file mode 100644 index 516bdd92..00000000 --- a/contracts/airdrop/src/contract.rs +++ /dev/null @@ -1,629 +0,0 @@ -use crate::crypto::verify_claim; -use crate::state::{CONFIG, STATE, USERS}; -use astroport::asset::addr_validate_to_lower; -use astroport_periphery::airdrop::{ - ClaimResponse, Config, Cw20HookMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, State, - UserInfo, -}; -use astroport_periphery::auction::Cw20HookMsg::DelegateAstroTokens; -use astroport_periphery::helpers::{build_send_cw20_token_msg, build_transfer_cw20_token_msg}; -use cosmwasm_std::{ - attr, entry_point, from_binary, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, - StdError, StdResult, Uint128, -}; -use cw2::set_contract_version; -use cw20::Cw20ReceiveMsg; - -/// Contract name that is used for migration. -const CONTRACT_NAME: &str = "astroport_airdrop"; -/// Contract version that is used for migration. -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); - -/// Creates a new contract with the specified parameters in the [`InstantiateMsg`]. -/// Returns the [`Response`] with the specified attributes if the operation was successful, or a [`StdError`] if -/// the contract was not created. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **env** is an object of type [`Env`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **msg** is a message of type [`InstantiateMsg`] which contains the basic settings for creating a contract. -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: InstantiateMsg, -) -> StdResult { - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - let from_timestamp = msg - .from_timestamp - .unwrap_or_else(|| env.block.time.seconds()); - - if msg.to_timestamp <= from_timestamp { - return Err(StdError::generic_err( - "Invalid airdrop claim window closure timestamp", - )); - } - - let owner = if let Some(owner) = msg.owner { - addr_validate_to_lower(deps.api, &owner)? - } else { - info.sender - }; - - let config = Config { - owner, - astro_token_address: addr_validate_to_lower(deps.api, &msg.astro_token_address)?, - merkle_roots: msg.merkle_roots.unwrap_or_default(), - from_timestamp, - to_timestamp: msg.to_timestamp, - auction_contract_address: None, - are_claims_enabled: false, - }; - - CONFIG.save(deps.storage, &config)?; - STATE.save(deps.storage, &State::default())?; - - Ok(Response::default()) -} - -/// ## Description -/// Exposes all the execute functions available in the contract. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **env** is an object of type [`Env`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **msg** is an object of type [`ExecuteMsg`]. -/// -/// ## Execute messages -/// -/// * **ExecuteMsg::Receive(msg)** Parse incoming messages from the ASTRO token. -/// -/// * **ExecuteMsg::UpdateConfig { -/// owner, -/// auction_contract_address, -/// merkle_roots, -/// from_timestamp, -/// to_timestamp, -/// }** Admin function to update any of the configuration parameters. -/// -/// * **ExecuteMsg::Claim { -/// claim_amount, -/// merkle_proof, -/// root_index, -/// }** Executes an airdrop claim for Users. -/// -/// * **ExecuteMsg::DelegateAstroToBootstrapAuction { amount_to_delegate }** Delegates ASTRO to bootstrap auction contract. -/// -/// * **ExecuteMsg::EnableClaims {}** Enables ASTRO withdrawals by the airdrop recipients. -/// -/// * **ExecuteMsg::WithdrawAirdropReward {}** Facilitates ASTRO withdrawal for airdrop recipients -/// -/// * **ExecuteMsg::TransferUnclaimedTokens { recipient, amount }** Transfers unclaimed ASTRO tokens available with the contract to the recipient address. -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - match msg { - ExecuteMsg::Receive(msg) => receive_cw20(deps, info, msg), - ExecuteMsg::UpdateConfig { - owner, - auction_contract_address, - merkle_roots, - from_timestamp, - to_timestamp, - } => handle_update_config( - deps, - env, - info, - owner, - auction_contract_address, - merkle_roots, - from_timestamp, - to_timestamp, - ), - ExecuteMsg::Claim { - claim_amount, - merkle_proof, - root_index, - } => handle_claim(deps, env, info, claim_amount, merkle_proof, root_index), - ExecuteMsg::DelegateAstroToBootstrapAuction { amount_to_delegate } => { - handle_delegate_astro_to_bootstrap_auction(deps, info, amount_to_delegate) - } - ExecuteMsg::EnableClaims {} => handle_enable_claims(deps, info), - ExecuteMsg::WithdrawAirdropReward {} => handle_withdraw_airdrop_rewards(deps, info), - ExecuteMsg::TransferUnclaimedTokens { recipient, amount } => { - handle_transfer_unclaimed_tokens(deps, env, info, recipient, amount) - } - } -} - -/// Receives a message of type [`Cw20ReceiveMsg`] and processes it depending on the received template. -/// If the template is not found in the received message, then an [`StdError`] is returned, -/// otherwise it returns the [`Response`] with the specified attributes if the operation was successful. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **cw20_msg** is an object of type [`Cw20ReceiveMsg`]. This is the CW20 message that has to be processed. -pub fn receive_cw20( - deps: DepsMut, - info: MessageInfo, - cw20_msg: Cw20ReceiveMsg, -) -> Result { - let config = CONFIG.load(deps.storage)?; - - if info.sender != config.astro_token_address { - return Err(StdError::generic_err("Only astro tokens are received!")); - } - - // CHECK ::: Amount needs to be valid - if cw20_msg.amount.is_zero() { - return Err(StdError::generic_err("Amount must be greater than 0")); - } - - match from_binary(&cw20_msg.msg)? { - Cw20HookMsg::IncreaseAstroIncentives {} => { - handle_increase_astro_incentives(deps, cw20_msg.amount) - } - } -} - -/// Exposes all the queries available in the contract. -/// ## Params -/// * **deps** is an object of type [`Deps`]. -/// -/// * **_env** is an object of type [`Env`]. -/// -/// * **msg** is an object of type [`QueryMsg`]. -/// -/// ## Queries -/// * **QueryMsg::Config {}** Returns the config info. -/// -/// * **QueryMsg::State {}** Returns the contract's state info. -/// -/// * **QueryMsg::HasUserClaimed { address }** Returns a boolean value indicating -/// if the corresponding address have yet claimed their airdrop or not. -/// -/// * **QueryMsg::UserInfo { address }** Returns user's airdrop claim state. -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::Config {} => to_binary(&CONFIG.load(deps.storage)?), - QueryMsg::State {} => to_binary(&STATE.load(deps.storage)?), - QueryMsg::HasUserClaimed { address } => to_binary(&query_user_claimed(deps, address)?), - QueryMsg::UserInfo { address } => to_binary(&query_user_info(deps, address)?), - } -} - -/// Used for contract migration. Returns a default object of type [`Response`]. -/// ## Params -/// * **_deps** is an object of type [`DepsMut`]. -/// -/// * **_env** is an object of type [`Env`]. -/// -/// * **_msg** is an object of type [`MigrateMsg`]. -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult { - Ok(Response::default()) -} - -/// Admin function to update any of the configuration parameters.. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **env** is an object of type [`Env`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **owner** is an optional object of type [`String`] that contains address of the new owner. -/// -/// * **auction_contract_address** is an optional object of type [`String`] that contains address of the new auction contract address. -/// -/// * **merkle_roots** is an optional vector of type [`String`] that contains new Markle roots. -pub fn handle_update_config( - deps: DepsMut, - env: Env, - info: MessageInfo, - owner: Option, - auction_contract_address: Option, - merkle_roots: Option>, - from_timestamp: Option, - to_timestamp: Option, -) -> StdResult { - let mut config = CONFIG.load(deps.storage)?; - let mut attributes = vec![attr("action", "update_config")]; - - // CHECK :: ONLY OWNER CAN CALL THIS FUNCTION - if info.sender != config.owner { - return Err(StdError::generic_err("Only owner can update configuration")); - } - - if let Some(owner) = owner { - config.owner = addr_validate_to_lower(deps.api, &owner)?; - attributes.push(attr("new_owner", owner.as_str())) - } - - if let Some(auction_contract_address) = auction_contract_address { - match config.auction_contract_address { - Some(_) => { - return Err(StdError::generic_err("Auction contract already set.")); - } - None => { - config.auction_contract_address = - Some(addr_validate_to_lower(deps.api, &auction_contract_address)?); - attributes.push(attr("auction_contract", auction_contract_address)) - } - } - } - - if let Some(merkle_roots) = merkle_roots { - config.merkle_roots = merkle_roots - } - - if let Some(from_timestamp) = from_timestamp { - if env.block.time.seconds() >= config.from_timestamp { - return Err(StdError::generic_err( - "from_timestamp can't be changed after window starts", - )); - } - config.from_timestamp = from_timestamp; - attributes.push(attr("new_from_timestamp", from_timestamp.to_string())) - } - - if let Some(to_timestamp) = to_timestamp { - if env.block.time.seconds() >= config.from_timestamp && to_timestamp < config.to_timestamp { - return Err(StdError::generic_err( - "When window starts to_timestamp can only be increased", - )); - } - config.to_timestamp = to_timestamp; - attributes.push(attr("new_to_timestamp", to_timestamp.to_string())) - } - - if config.to_timestamp <= config.from_timestamp { - return Err(StdError::generic_err("Invalid airdrop claim window")); - } - - CONFIG.save(deps.storage, &config)?; - Ok(Response::new().add_attributes(attributes)) -} - -/// Increases ASTRO incentives. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **amount** is an object of type [`Uint128`]. -pub fn handle_increase_astro_incentives( - deps: DepsMut, - amount: Uint128, -) -> Result { - let mut state = STATE.load(deps.storage)?; - state.total_airdrop_size += amount; - state.unclaimed_tokens += amount; - - STATE.save(deps.storage, &state)?; - Ok(Response::new() - .add_attribute("action", "increase_astro_incentives") - .add_attribute("total_airdrop_size", state.total_airdrop_size)) -} - -/// Enables ASTRO withdrawals by the airdrop recipients. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -pub fn handle_enable_claims(deps: DepsMut, info: MessageInfo) -> StdResult { - let mut config = CONFIG.load(deps.storage)?; - - // CHECK :: ONLY AUCTION CONTRACT CAN CALL THIS FUNCTION - if info.sender - != config - .auction_contract_address - .clone() - .ok_or_else(|| StdError::generic_err("Auction contract not set"))? - { - return Err(StdError::generic_err("Unauthorized")); - } - - if config.are_claims_enabled { - return Err(StdError::generic_err("Claims already enabled")); - } - - config.are_claims_enabled = true; - - CONFIG.save(deps.storage, &config)?; - Ok(Response::new().add_attribute("action", "enable_claims")) -} - -/// Executes an airdrop claim for Users. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **env** is an object of type [`Env`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **claim_amount** is an object of type [`Uint128`]. Airdrop to be claimed by the user -/// -/// * **merkle_proof** is a vector of type [`String`]. Array of hashes to prove the input is a leaf of the Merkle Tree -/// -/// * **root_index** is a vector of type [`u32`]. Merkle Tree root identifier to be used for verification -pub fn handle_claim( - deps: DepsMut, - env: Env, - info: MessageInfo, - claim_amount: Uint128, - merkle_proof: Vec, - root_index: u32, -) -> Result { - let recipient = info.sender; - - let config = CONFIG.load(deps.storage)?; - let mut state = STATE.load(deps.storage)?; - - // CHECK :: IS AIRDROP CLAIM WINDOW OPEN ? - if config.from_timestamp > env.block.time.seconds() { - return Err(StdError::generic_err("Claim not allowed")); - } - - // CHECK :: IS AIRDROP CLAIM WINDOW OPEN ? - if config.to_timestamp < env.block.time.seconds() { - return Err(StdError::generic_err("Claim period has concluded")); - } - - let merkle_root = config - .merkle_roots - .get(root_index as usize) - .ok_or_else(|| StdError::generic_err("Incorrect Merkle Root Index"))?; - - if !verify_claim(&recipient, claim_amount, merkle_proof, merkle_root)? { - return Err(StdError::generic_err("Incorrect Merkle Proof")); - } - - let mut user_info = USERS.load(deps.storage, &recipient).unwrap_or_default(); - - // Check if addr has already claimed the tokens - if !user_info.claimed_amount.is_zero() { - return Err(StdError::generic_err("Already claimed")); - } - - let mut messages = vec![]; - - // check is sufficient ASTRO available - if state.unclaimed_tokens < claim_amount { - return Err(StdError::generic_err("Insufficient ASTRO available")); - } - - // TRANSFER ASTRO IF CLAIMS ARE ALLOWED (i.e LP bootstrap auction has concluded) - if config.are_claims_enabled { - messages.push(build_transfer_cw20_token_msg( - recipient.clone(), - config.astro_token_address.to_string(), - claim_amount, - )?); - - user_info.tokens_withdrawn = true; - } - - // Update amounts - state.unclaimed_tokens -= claim_amount; - user_info.claimed_amount = claim_amount; - - USERS.save(deps.storage, &recipient, &user_info)?; - STATE.save(deps.storage, &state)?; - - Ok(Response::new().add_messages(messages).add_attributes(vec![ - attr("action", "handle_claim"), - attr("addr", recipient), - attr("airdrop", claim_amount), - ])) -} - -/// Delegates ASTRO to bootstrap auction. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **amount_to_delegate** is an object of type [`Uint128`]. -pub fn handle_delegate_astro_to_bootstrap_auction( - deps: DepsMut, - info: MessageInfo, - amount_to_delegate: Uint128, -) -> Result { - let config = CONFIG.load(deps.storage)?; - - // CHECK :: HAS THE BOOTSTRAP AUCTION CONCLUDED ? - if config.are_claims_enabled { - return Err(StdError::generic_err("LP bootstrap auction has concluded")); - } - - let mut state = STATE.load(deps.storage)?; - let mut user_info = USERS.load(deps.storage, &info.sender)?; - - state.total_delegated_amount += amount_to_delegate; - user_info.delegated_amount += amount_to_delegate; - - // CHECK :: TOKENS BEING DELEGATED SHOULD NOT EXCEED USER'S CLAIMABLE AIRDROP AMOUNT - if user_info.delegated_amount > user_info.claimed_amount { - return Err(StdError::generic_err("Total amount being delegated for bootstrap auction cannot exceed your claimable airdrop balance")); - } - - // COSMOS MSG :: DELEGATE ASTRO TOKENS TO LP BOOTSTRAP AUCTION CONTRACT - let msg = to_binary(&DelegateAstroTokens { - user_address: info.sender.to_string(), - })?; - - let delegate_msg = build_send_cw20_token_msg( - config - .auction_contract_address - .expect("Auction contract not set") - .to_string(), - config.astro_token_address.to_string(), - amount_to_delegate, - msg, - )?; - - // STATE UPDATE : SAVE UPDATED STATES - USERS.save(deps.storage, &info.sender, &user_info)?; - STATE.save(deps.storage, &state)?; - - Ok(Response::new() - .add_messages(vec![delegate_msg]) - .add_attributes(vec![ - attr("action", "delegate_astro_to_bootstrap_auction"), - attr("user", info.sender.to_string()), - attr("amount_delegated", amount_to_delegate), - ])) -} - -/// Withdraws airdrop rewards. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -pub fn handle_withdraw_airdrop_rewards( - deps: DepsMut, - info: MessageInfo, -) -> Result { - let config = CONFIG.load(deps.storage)?; - let mut user_info = USERS.load(deps.storage, &info.sender)?; - - // CHECK :: HAS THE BOOTSTRAP AUCTION CONCLUDED ? - if !config.are_claims_enabled { - return Err(StdError::generic_err( - "LP bootstrap auction in progress. Claims not allowed during this period", - )); - } - - // CHECK :: HAS USER ALREADY WITHDRAWN THEIR REWARDS ? - if user_info.tokens_withdrawn { - return Err(StdError::generic_err("Tokens have already been withdrawn")); - } - - // TRANSFER ASTRO IF CLAIMS ARE ALLOWED (i.e LP bootstrap auction has concluded) - user_info.tokens_withdrawn = true; - - let tokens_to_withdraw = user_info.claimed_amount - user_info.delegated_amount; - if tokens_to_withdraw.is_zero() { - return Err(StdError::generic_err("Nothing to withdraw")); - } - - let transfer_msg = build_transfer_cw20_token_msg( - info.sender.clone(), - config.astro_token_address.to_string(), - tokens_to_withdraw, - )?; - - USERS.save(deps.storage, &info.sender, &user_info)?; - - Ok(Response::new() - .add_message(transfer_msg) - .add_attributes(vec![ - attr("action", "Airdrop::ExecuteMsg::WithdrawAirdropRewards"), - attr("user", info.sender.to_string()), - attr("claimed_amount", tokens_to_withdraw), - attr("total_airdrop", user_info.claimed_amount), - ])) -} - -/// Transfers unclaimed tokens. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`DepsMut`]. -/// -/// * **env** is an object of type [`Env`]. -/// -/// * **info** is an object of type [`MessageInfo`]. -/// -/// * **recipient** is an object of type [`String`]. Recipient receiving the ASTRO tokens -/// -/// * **amount** is an object of type [`Uint128`]. Amount of ASTRO to be transferred -pub fn handle_transfer_unclaimed_tokens( - deps: DepsMut, - env: Env, - info: MessageInfo, - recipient: String, - amount: Uint128, -) -> Result { - let config = CONFIG.load(deps.storage)?; - let mut state = STATE.load(deps.storage)?; - - // CHECK :: CAN ONLY BE CALLED BY THE OWNER - if info.sender != config.owner { - return Err(StdError::generic_err("Sender not authorized!")); - } - - // CHECK :: CAN ONLY BE CALLED AFTER THE CLAIM PERIOD IS OVER - if config.to_timestamp > env.block.time.seconds() { - return Err(StdError::generic_err(format!( - "{} seconds left before unclaimed tokens can be transferred", - { config.to_timestamp - env.block.time.seconds() } - ))); - } - - // CHECK :: Amount needs to be less than unclaimed_tokens balance - if amount > state.unclaimed_tokens { - return Err(StdError::generic_err( - "Amount cannot exceed unclaimed token balance", - )); - } - - // COSMOS MSG :: TRANSFER ASTRO TOKENS - state.unclaimed_tokens -= amount; - let transfer_msg = build_transfer_cw20_token_msg( - addr_validate_to_lower(deps.api, &recipient)?, - config.astro_token_address.to_string(), - amount, - )?; - - STATE.save(deps.storage, &state)?; - Ok(Response::new() - .add_message(transfer_msg) - .add_attributes(vec![ - attr("action", "transfer_unclaimed_tokens"), - attr("recipient", recipient), - attr("amount", amount), - ])) -} - -/// Returns details around user's ASTRO Airdrop claim. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`Deps`]. -/// -/// * **user_address** is an object of type [`String`]. -fn query_user_info(deps: Deps, user_address: String) -> StdResult { - let user_info = USERS - .may_load( - deps.storage, - &addr_validate_to_lower(deps.api, &user_address)?, - )? - .unwrap_or_default(); - Ok(user_info) -} - -/// Returns a boolean value indicating if the corresponding address have yet claimed their airdrop or not. Returns a [`StdError`] on failure. -/// ## Params -/// * **deps** is an object of type [`Deps`]. -/// -/// * **address** is an object of type [`String`]. -fn query_user_claimed(deps: Deps, address: String) -> StdResult { - let user_address = addr_validate_to_lower(deps.api, &address)?; - let user_info = USERS - .may_load(deps.storage, &user_address)? - .unwrap_or_default(); - - Ok(ClaimResponse { - is_claimed: !user_info.claimed_amount.is_zero(), - }) -} diff --git a/contracts/airdrop/src/crypto.rs b/contracts/airdrop/src/crypto.rs deleted file mode 100644 index 5c436967..00000000 --- a/contracts/airdrop/src/crypto.rs +++ /dev/null @@ -1,49 +0,0 @@ -use cosmwasm_std::{Addr, StdError, StdResult, Uint128}; -use sha3::{Digest, Keccak256}; -use std::cmp::Ordering; -use std::convert::TryInto; - -/// Verify whether a claim is valid. -/// ## Params -/// * **account** is an object of type [`Addr`]. Account on behalf of which the airdrop is to be claimed (etherum addresses without `0x` prefix) -/// -/// * **amount** is an object of type [`Uint128`]. Airdrop amount to be claimed by the user -/// -/// * **merkle_proof** is a vector of type [`String`]. Array of hashes to prove the input is a leaf of the Merkle Tree -/// -/// * **merkle_root** is an object of type [`str`]. Hash of Merkle tree's root -pub fn verify_claim( - account: &Addr, - amount: Uint128, - merkle_proof: Vec, - merkle_root: &str, -) -> StdResult { - let leaf = account.to_string() + &amount.to_string(); - let mut hash_buf = Keccak256::digest(leaf.as_bytes()) - .as_slice() - .try_into() - .map_err(|_| StdError::generic_err("Wrong length"))?; - let mut hash_str: String; - - for p in merkle_proof { - let mut proof_buf: [u8; 32] = [0; 32]; - hex::decode_to_slice(p, &mut proof_buf).unwrap(); - let proof_buf_str = hex::encode(proof_buf); - hash_str = hex::encode(hash_buf); - - if proof_buf_str.cmp(&hash_str.clone()) == Ordering::Greater { - hash_buf = Keccak256::digest(&[hash_buf, proof_buf].concat()) - .as_slice() - .try_into() - .map_err(|_| StdError::generic_err("Wrong length"))? - } else { - hash_buf = Keccak256::digest(&[proof_buf, hash_buf].concat()) - .as_slice() - .try_into() - .map_err(|_| StdError::generic_err("Wrong length"))? - } - } - - hash_str = hex::encode(hash_buf); - Ok(merkle_root == hash_str) -} diff --git a/contracts/airdrop/src/lib.rs b/contracts/airdrop/src/lib.rs deleted file mode 100644 index b9332de6..00000000 --- a/contracts/airdrop/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod contract; -pub mod crypto; -pub mod state; diff --git a/contracts/airdrop/src/state.rs b/contracts/airdrop/src/state.rs deleted file mode 100644 index 87d19e16..00000000 --- a/contracts/airdrop/src/state.rs +++ /dev/null @@ -1,10 +0,0 @@ -use astroport_periphery::airdrop::{Config, State, UserInfo}; -use cosmwasm_std::Addr; -use cw_storage_plus::{Item, Map}; - -/// Stores the contract config at the given key -pub const CONFIG: Item = Item::new("config"); -/// Stores the global state of contract at the given key -pub const STATE: Item = Item::new("state"); -/// Stores user information for the specified address -pub const USERS: Map<&Addr, UserInfo> = Map::new("users"); diff --git a/contracts/airdrop/tests/integration.rs b/contracts/airdrop/tests/integration.rs deleted file mode 100644 index f9ebed22..00000000 --- a/contracts/airdrop/tests/integration.rs +++ /dev/null @@ -1,1438 +0,0 @@ -use astroport_periphery::airdrop::{Config, State, UserInfo}; -use astroport_periphery::{ - airdrop::{ClaimResponse, Cw20HookMsg, ExecuteMsg, InstantiateMsg, QueryMsg}, - auction::{ExecuteMsg as AuctionExecuteMsg, UpdateConfigMsg}, -}; - -use cosmwasm_std::{attr, to_binary, Addr, Timestamp, Uint128}; -use cw20::Cw20ExecuteMsg; -use cw_multi_test::{App, ContractWrapper, Executor}; - -fn mock_app() -> App { - App::default() -} - -fn init_contracts(app: &mut App) -> (Addr, Addr, InstantiateMsg, u64) { - let owner = Addr::unchecked("contract_owner"); - - // Instantiate ASTRO Token Contract - let astro_token_contract = Box::new(ContractWrapper::new( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let astro_token_code_id = app.store_code(astro_token_contract); - - let msg = astroport::token::InstantiateMsg { - name: String::from("Astro token"), - symbol: String::from("ASTRO"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }; - - let astro_token_instance = app - .instantiate_contract( - astro_token_code_id, - owner.clone(), - &msg, - &[], - String::from("ASTRO"), - None, - ) - .unwrap(); - - // Instantiate Airdrop Contract - let airdrop_contract = Box::new(ContractWrapper::new( - astroport_airdrop::contract::execute, - astroport_airdrop::contract::instantiate, - astroport_airdrop::contract::query, - )); - - let airdrop_code_id = app.store_code(airdrop_contract); - - let aidrop_instantiate_msg = InstantiateMsg { - owner: Some(owner.clone().to_string()), - astro_token_address: astro_token_instance.clone().into_string(), - merkle_roots: Some(vec!["merkle_roots".to_string()]), - from_timestamp: Some(1571897419), - to_timestamp: 1581797419, - }; - - // Init contract - let airdrop_instance = app - .instantiate_contract( - airdrop_code_id, - owner.clone(), - &aidrop_instantiate_msg, - &[], - "airdrop", - None, - ) - .unwrap(); - - ( - airdrop_instance, - astro_token_instance, - aidrop_instantiate_msg, - astro_token_code_id, - ) -} - -fn mint_some_astro( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, - amount: Uint128, - to: String, -) { - let msg = cw20::Cw20ExecuteMsg::Mint { - recipient: to.clone(), - amount: amount, - }; - let res = app - .execute_contract(owner.clone(), astro_token_instance.clone(), &msg, &[]) - .unwrap(); - assert_eq!(res.events[1].attributes[1], attr("action", "mint")); - assert_eq!(res.events[1].attributes[2], attr("to", to)); - assert_eq!(res.events[1].attributes[3], attr("amount", amount)); -} - -// Helper function. Enables claims (ASTRO Withdrawals) from the Airdrop contract -fn enable_claims(app: &mut App, airdrop_instance: Addr, owner: Addr) { - let msg = ExecuteMsg::EnableClaims {}; - let auction_contract_address = String::from("auction_contract_address"); - - // should successfully set auction contract address - app.execute_contract( - owner, - airdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: Some(auction_contract_address.clone()), - merkle_roots: None, - from_timestamp: None, - to_timestamp: None, - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(auction_contract_address.clone()), - airdrop_instance.clone(), - &msg, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - assert_eq!(true, resp.are_claims_enabled); -} - -#[test] -fn proper_initialization() { - let mut app = mock_app(); - let (airdrop_instance, astro_token_instance, init_msg, _) = init_contracts(&mut app); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config - assert_eq!(init_msg.astro_token_address, resp.astro_token_address); - assert_eq!(None, resp.auction_contract_address); - assert_eq!(init_msg.owner.clone().unwrap(), resp.owner); - assert_eq!(init_msg.merkle_roots.unwrap(), resp.merkle_roots); - assert_eq!(init_msg.from_timestamp.unwrap(), resp.from_timestamp); - assert_eq!(init_msg.to_timestamp, resp.to_timestamp); - - // Check state - let resp: State = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - - assert_eq!(Uint128::zero(), resp.total_airdrop_size); - assert_eq!(Uint128::zero(), resp.unclaimed_tokens); - assert_eq!(Uint128::zero(), resp.total_delegated_amount); - - // mint ASTRO for to Owner - mint_some_astro( - &mut app, - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - init_msg.owner.clone().unwrap(), - ); - - // Set ASTRO airdrop incentives - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_token_instance, - &Cw20ExecuteMsg::Send { - amount: Uint128::new(100_000_000000), - contract: airdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - // Check state - let resp: State = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - - assert_eq!(Uint128::new(100_000_000000), resp.total_airdrop_size); - assert_eq!(Uint128::new(100_000_000000), resp.unclaimed_tokens); - assert_eq!(Uint128::new(0), resp.total_delegated_amount); -} - -#[test] -fn update_config() { - let mut app = mock_app(); - let (airdrop_instance, _, init_msg, _) = init_contracts(&mut app); - - // Only owner can update - let err = app - .execute_contract( - Addr::unchecked("wrong_owner"), - airdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: None, - merkle_roots: None, - from_timestamp: None, - to_timestamp: None, - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - err.root_cause().to_string(), - "Generic error: Only owner can update configuration" - ); - - let new_owner = String::from("new_owner"); - let auction_contract_address = String::from("auction_contract_address"); - let merkle_roots = vec!["new_merkle_roots".to_string()]; - let from_timestamp = 1571997419; - let to_timestamp = 1591797419; - - let update_msg = ExecuteMsg::UpdateConfig { - owner: Some(new_owner.clone()), - auction_contract_address: Some(auction_contract_address.clone()), - merkle_roots: Some(merkle_roots.clone()), - from_timestamp: Some(from_timestamp), - to_timestamp: Some(to_timestamp), - }; - - // should be a success - app.execute_contract( - Addr::unchecked(init_msg.owner.unwrap()), - airdrop_instance.clone(), - &update_msg, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config and make sure all fields are updated - assert_eq!(new_owner, resp.owner); - assert_eq!( - auction_contract_address, - resp.auction_contract_address.unwrap().to_string() - ); - assert_eq!(merkle_roots, resp.merkle_roots); - assert_eq!(from_timestamp, resp.from_timestamp); - assert_eq!(to_timestamp, resp.to_timestamp); -} - -#[cfg(test)] -#[test] -fn test_transfer_unclaimed_tokens() { - let mut app = mock_app(); - let (airdrop_instance, astro_token_instance, init_msg, _) = init_contracts(&mut app); - - // mint ASTRO for to Owner - mint_some_astro( - &mut app, - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::from(100_000_000_000u64), - init_msg.owner.clone().unwrap(), - ); - - // Set ASTRO airdrop incentives - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(100_000_000_000u64), - contract: airdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - // Check Airdrop Contract balance - let bal_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_token_instance.clone(), - &cw20::Cw20QueryMsg::Balance { - address: airdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100_000_000_000u64), bal_resp.balance); - - // Can only be called by the owner - let err = app - .execute_contract( - Addr::unchecked("wrong_owner"), - airdrop_instance.clone(), - &ExecuteMsg::TransferUnclaimedTokens { - recipient: "recipient".to_string(), - amount: Uint128::from(1000000 as u64), - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - err.root_cause().to_string(), - "Generic error: Sender not authorized!" - ); - - // claim period is not over - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1571897419) - }); - - // Can only be called after the claim period is over - let err = app - .execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - airdrop_instance.clone(), - &ExecuteMsg::TransferUnclaimedTokens { - recipient: "recipient".to_string(), - amount: Uint128::from(1000000 as u64), - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - err.root_cause().to_string(), - "Generic error: 9900000 seconds left before unclaimed tokens can be transferred" - ); - - // claim period is over - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1581797419) - }); - - // Amount needs to be less than unclaimed_tokens balance - let err = app - .execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - airdrop_instance.clone(), - &ExecuteMsg::TransferUnclaimedTokens { - recipient: "recipient".to_string(), - amount: Uint128::from(100_000_000_0000 as u64), - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - err.root_cause().to_string(), - "Generic error: Amount cannot exceed unclaimed token balance" - ); - - // Should successfully transfer and update state - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - airdrop_instance.clone(), - &ExecuteMsg::TransferUnclaimedTokens { - recipient: "recipient".to_string(), - amount: Uint128::from(100_000_00 as u64), - }, - &[], - ) - .unwrap(); - - let state_resp: State = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - - // Check config and make sure all fields are updated - assert_eq!( - Uint128::from(100_000_000_000u64), - state_resp.total_airdrop_size - ); - assert_eq!(Uint128::from(0u32), state_resp.total_delegated_amount); - assert_eq!(Uint128::from(99990000000u64), state_resp.unclaimed_tokens); -} - -#[cfg(test)] -#[test] -fn test_claim_by_terra_user() { - let mut app = mock_app(); - let (airdrop_instance, astro_instance, init_msg, _) = init_contracts(&mut app); - - // mint ASTRO for to Owner - mint_some_astro( - &mut app, - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_instance.clone(), - Uint128::from(100_000_000_000u64), - init_msg.owner.clone().unwrap(), - ); - - // Set ASTRO airdrop incentives - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_instance.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(100_000_000_000u64), - contract: airdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - // Check Airdrop Contract balance - let bal_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_instance, - &cw20::Cw20QueryMsg::Balance { - address: airdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100_000_000_000u64), bal_resp.balance); - - let merkle_roots = - vec!["cdcdfad1c342f5f55a2639dcae7321a64cd000807fa24c2c4ddaa944fd52d34e".to_string()]; - let update_msg = ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: None, - merkle_roots: Some(merkle_roots.clone()), - from_timestamp: None, - to_timestamp: None, - }; - - // Update Config :: should be a success - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - airdrop_instance.clone(), - &update_msg, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config and make sure all fields are updated - assert_eq!(init_msg.owner.clone().unwrap(), resp.owner); - assert_eq!(merkle_roots, resp.merkle_roots); - assert_eq!(init_msg.from_timestamp.unwrap(), resp.from_timestamp); - assert_eq!(init_msg.to_timestamp, resp.to_timestamp); - - // Claim period has not started yet - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1571798419) - }); - - let mut claim_msg = ExecuteMsg::Claim { - claim_amount: Uint128::from(250000000 as u64), - merkle_proof: vec![ - "7719b79a65e5aa0bbfd144cf5373138402ab1c374d9049e490b5b61c23d90065".to_string(), - "60368f2058e0fb961a7721a241f9b973c3dd6c57e10a627071cd81abca6aa490".to_string(), - ], - root_index: 0, - }; - let mut claim_msg_wrong_amount = ExecuteMsg::Claim { - claim_amount: Uint128::from(210000000 as u64), - merkle_proof: vec![ - "7719b79a65e5aa0bbfd144cf5373138402ab1c374d9049e490b5b61c23d90065".to_string(), - "60368f2058e0fb961a7721a241f9b973c3dd6c57e10a627071cd81abca6aa490".to_string(), - ], - root_index: 0, - }; - let mut claim_msg_incorrect_proof = ExecuteMsg::Claim { - claim_amount: Uint128::from(250000000 as u64), - merkle_proof: vec![ - "7719b79a65e4aa0bbfd144cf5373138402ab1c374d9049e490b5b61c23d90065".to_string(), - "60368f2058e0fb961a7721a241f9b973c3dd6c57e10a627071cd81abca6aa490".to_string(), - ], - root_index: 0, - }; - - // ################################ - // USER #1 :: Claims not allowed. ASTRO Rewards will Not be transferred to the user - // ################################ - - // **** "Claim not allowed" Error should be returned **** - let mut claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Claim not allowed" - ); - - // Update Block to test successful claim - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1571897424) - }); - - // **** "Incorrect Merkle Root Index" Error should be returned **** - claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &ExecuteMsg::Claim { - claim_amount: Uint128::from(250000000 as u64), - merkle_proof: vec![ - "7719b79a65e4aa0bbfd144cf5373138402ab1c374d9049e490b5b61c23d90065".to_string(), - "60368f2058e0fb961a7721a241f9b973c3dd6c57e10a627071cd81abca6aa490".to_string(), - ], - root_index: 5, - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Incorrect Merkle Root Index" - ); - - // **** "Incorrect Merkle Proof" Error should be returned **** - claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg_incorrect_proof, - &[], - ) - .unwrap_err(); - - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Incorrect Merkle Proof" - ); - - // **** "Incorrect Merkle Proof" Error should be returned **** - claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg_wrong_amount, - &[], - ) - .unwrap_err(); - - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Incorrect Merkle Proof" - ); - - // **** User should successfully claim the Airdrop **** - - // Check :: User hasn't yet claimed the airdrop - let resp: ClaimResponse = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::HasUserClaimed { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!(false, resp.is_claimed); - - // Should be a success - let mut success_ = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap(); - - assert_eq!( - success_.events[1].attributes[1], - attr("action", "handle_claim") - ); - assert_eq!( - success_.events[1].attributes[2], - attr("addr", "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp") - ); - assert_eq!( - success_.events[1].attributes[3], - attr("airdrop", "250000000") - ); - - // Check :: User successfully claimed the airdrop - let mut claim_query_resp: ClaimResponse = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::HasUserClaimed { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!(true, claim_query_resp.is_claimed); - - // Check :: User state - let mut user_info_query_resp: UserInfo = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::UserInfo { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(250000000u64), - user_info_query_resp.claimed_amount - ); - assert_eq!(Uint128::from(0u64), user_info_query_resp.delegated_amount); - assert_eq!(false, user_info_query_resp.tokens_withdrawn); - - // Check :: Contract state - let mut state_query_resp: State = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(100_000_000_000u64), - state_query_resp.total_airdrop_size - ); - assert_eq!(Uint128::from(0u64), state_query_resp.total_delegated_amount); - assert_eq!( - Uint128::from(99750000000u64), - state_query_resp.unclaimed_tokens - ); - - // **** "Already claimed" Error should be returned **** - - claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Already claimed" - ); - - // Enable ASTRO Withdrawals - enable_claims( - &mut app, - Addr::unchecked(airdrop_instance.clone()), - Addr::unchecked(init_msg.owner.unwrap()), - ); - - // ################################ - // USER #2 :: ASTRO Rewards will be transferred to the user - // ################################ - - claim_msg = ExecuteMsg::Claim { - claim_amount: Uint128::from(1 as u64), - merkle_proof: vec![ - "7fd0f6ac4074cef9f89eedcf72459ad7b0891855f8084b54dc7de7569849d1c8".to_string(), - "4fab6b0ef8d988835ad968d03d61de408772d033e9ce734394bb623309c5d7fc".to_string(), - ], - root_index: 0, - }; - claim_msg_wrong_amount = ExecuteMsg::Claim { - claim_amount: Uint128::from(2 as u64), - merkle_proof: vec![ - "7fd0f6ac4074cef9f89eedcf72459ad7b0891855f8084b54dc7de7569849d1c8".to_string(), - "4fab6b0ef8d988835ad968d03d61de408772d033e9ce734394bb623309c5d7fc".to_string(), - ], - root_index: 0, - }; - claim_msg_incorrect_proof = ExecuteMsg::Claim { - claim_amount: Uint128::from(1 as u64), - merkle_proof: vec![ - "7fd0f6ac4074cef1f89eedcf72459ad7b0891855f8084b54dc7de7569849d1c8".to_string(), - "4fab6b0ef8d988835ad968d03d61de408772d033e9ce734394bb623309c5d7fc".to_string(), - ], - root_index: 0, - }; - - // **** "Incorrect Merkle Root Index" Error should be returned **** - claim_f = app - .execute_contract( - Addr::unchecked("terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string()), - airdrop_instance.clone(), - &ExecuteMsg::Claim { - claim_amount: Uint128::from(1 as u64), - merkle_proof: vec![ - "7fd0f6ac4074cef9f89eedcf72459ad7b0891855f8084b54dc7de7569849d1c8".to_string(), - "4fab6b0ef8d988835ad968d03d61de408772d033e9ce734394bb623309c5d7fc".to_string(), - ], - root_index: 5, - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Incorrect Merkle Root Index" - ); - - // **** "Incorrect Merkle Proof" Error should be returned **** - claim_f = app - .execute_contract( - Addr::unchecked("terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string()), - airdrop_instance.clone(), - &claim_msg_incorrect_proof, - &[], - ) - .unwrap_err(); - - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Incorrect Merkle Proof" - ); - - // **** "Incorrect Merkle Proof" Error should be returned **** - claim_f = app - .execute_contract( - Addr::unchecked("terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string()), - airdrop_instance.clone(), - &claim_msg_wrong_amount, - &[], - ) - .unwrap_err(); - - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Incorrect Merkle Proof" - ); - - // **** User should successfully claim the Airdrop **** - - // Check :: User hasn't yet claimed the airdrop - let resp: ClaimResponse = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::HasUserClaimed { - address: "terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string(), - }, - ) - .unwrap(); - assert_eq!(false, resp.is_claimed); - - // Should be a success - success_ = app - .execute_contract( - Addr::unchecked("terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap(); - - assert_eq!( - success_.events[1].attributes[1], - attr("action", "handle_claim") - ); - assert_eq!( - success_.events[1].attributes[2], - attr("addr", "terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95") - ); - assert_eq!(success_.events[1].attributes[3], attr("airdrop", "1")); - - // Check user ASTRO balance - let bal_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_instance, - &cw20::Cw20QueryMsg::Balance { - address: "terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(1u64), bal_resp.balance); - - // Check :: User successfully claimed the airdrop - claim_query_resp = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::HasUserClaimed { - address: "terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string(), - }, - ) - .unwrap(); - assert_eq!(true, claim_query_resp.is_claimed); - - // Check :: User state - user_info_query_resp = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::UserInfo { - address: "terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(1u64), user_info_query_resp.claimed_amount); - assert_eq!(Uint128::from(0u64), user_info_query_resp.delegated_amount); - assert_eq!(true, user_info_query_resp.tokens_withdrawn); - - // Check :: Contract state - state_query_resp = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(100000000000u64), - state_query_resp.total_airdrop_size - ); - assert_eq!(Uint128::from(0u64), state_query_resp.total_delegated_amount); - assert_eq!( - Uint128::from(99749999999u64), - state_query_resp.unclaimed_tokens - ); - - // **** "Already claimed" Error should be returned **** - - claim_f = app - .execute_contract( - Addr::unchecked("terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Already claimed" - ); - - // Claim period has concluded - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(2571797419) - }); - - // **** "Claim period has concluded" Error should be returned **** - - claim_f = app - .execute_contract( - Addr::unchecked("terra1757tkx08n0cqrw7p86ny9lnxsqeth0wgp0em95".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Claim period has concluded" - ); -} - -#[cfg(test)] -#[test] -fn test_enable_claims() { - let mut app = mock_app(); - let (airdrop_instance, _, init_msg, _) = init_contracts(&mut app); - let auction_contract_address = String::from("auction_contract_address"); - - // should successfully set auction contract address - app.execute_contract( - Addr::unchecked(init_msg.owner.unwrap()), - airdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: Some(auction_contract_address.clone()), - merkle_roots: None, - from_timestamp: None, - to_timestamp: None, - }, - &[], - ) - .unwrap(); - - let msg = ExecuteMsg::EnableClaims {}; - - // ###### Should give "Unauthorized" Error ###### - - let mut resp_f = app - .execute_contract( - Addr::unchecked("not_bootstrap_auction_contract".to_string()), - airdrop_instance.clone(), - &msg, - &[], - ) - .unwrap_err(); - assert_eq!( - resp_f.root_cause().to_string(), - "Generic error: Unauthorized" - ); - - // ###### Should successfully enable claims ###### - - app.execute_contract( - Addr::unchecked(auction_contract_address.clone()), - airdrop_instance.clone(), - &msg, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - assert_eq!(true, resp.are_claims_enabled); - - // ###### Should give "Claims already enabled" Error ###### - - resp_f = app - .execute_contract( - Addr::unchecked(auction_contract_address.clone()), - airdrop_instance.clone(), - &msg, - &[], - ) - .unwrap_err(); - assert_eq!( - resp_f.root_cause().to_string(), - "Generic error: Claims already enabled" - ); -} - -#[cfg(test)] -#[test] -fn test_withdraw_airdrop_rewards() { - let mut app = mock_app(); - let (airdrop_instance, astro_instance, init_msg, _) = init_contracts(&mut app); - - // mint ASTRO for to Owner - mint_some_astro( - &mut app, - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_instance.clone(), - Uint128::from(100_000_000_000u64), - init_msg.owner.clone().unwrap(), - ); - - // Set ASTRO airdrop incentives - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_instance.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(100_000_000_000u64), - contract: airdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - // Check Airdrop Contract balance - let bal_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_instance, - &cw20::Cw20QueryMsg::Balance { - address: airdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100_000_000_000u64), bal_resp.balance); - - let merkle_roots = - vec!["cdcdfad1c342f5f55a2639dcae7321a64cd000807fa24c2c4ddaa944fd52d34e".to_string()]; - - let update_msg = ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: None, - merkle_roots: Some(merkle_roots.clone()), - from_timestamp: None, - to_timestamp: None, - }; - - // Update Config :: should be a success - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - airdrop_instance.clone(), - &update_msg, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config and make sure all fields are updated - assert_eq!(init_msg.owner.clone().unwrap(), resp.owner); - assert_eq!(merkle_roots, resp.merkle_roots); - assert_eq!(init_msg.from_timestamp.unwrap(), resp.from_timestamp); - assert_eq!(init_msg.to_timestamp, resp.to_timestamp); - - // Update Block to test successful claim - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1571897424) - }); - - // ################################ - // TERRA USER :: Claims not allowed. ASTRO Rewards will Not be transferred to the user - // ################################ - - let claim_msg = ExecuteMsg::Claim { - claim_amount: Uint128::from(250000000 as u64), - merkle_proof: vec![ - "7719b79a65e5aa0bbfd144cf5373138402ab1c374d9049e490b5b61c23d90065".to_string(), - "60368f2058e0fb961a7721a241f9b973c3dd6c57e10a627071cd81abca6aa490".to_string(), - ], - root_index: 0, - }; - - // **** User should successfully claim the Airdrop **** - - // Check :: User hasn't yet claimed the airdrop - let resp: ClaimResponse = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::HasUserClaimed { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!(false, resp.is_claimed); - - // Should be a success - let success_ = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap(); - - assert_eq!( - success_.events[1].attributes[1], - attr("action", "handle_claim") - ); - assert_eq!( - success_.events[1].attributes[2], - attr("addr", "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp") - ); - assert_eq!( - success_.events[1].attributes[3], - attr("airdrop", "250000000") - ); - - // Check :: Terra User successfully claimed the airdrop - let claim_query_resp: ClaimResponse = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::HasUserClaimed { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!(true, claim_query_resp.is_claimed); - - // Check :: User state - let user_info_query_resp: UserInfo = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::UserInfo { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(250000000u64), - user_info_query_resp.claimed_amount - ); - assert_eq!(Uint128::from(0u64), user_info_query_resp.delegated_amount); - assert_eq!(false, user_info_query_resp.tokens_withdrawn); - - // Check :: Contract state - let state_query_resp: State = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(100_000_000_000u64), - state_query_resp.total_airdrop_size - ); - assert_eq!(Uint128::from(0u64), state_query_resp.total_delegated_amount); - assert_eq!( - Uint128::from(99750000000u64), - state_query_resp.unclaimed_tokens - ); - - // **** "Already claimed" Error should be returned **** - - let claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Already claimed" - ); - - // ################# - // ENABLE CLAIMS :: - // ################# - - // Enable ASTRO Withdrawals - enable_claims( - &mut app, - Addr::unchecked(airdrop_instance.clone()), - Addr::unchecked(init_msg.owner.clone().unwrap()), - ); - - // Should be a success - app.execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &ExecuteMsg::WithdrawAirdropReward {}, - &[], - ) - .unwrap(); - - // Check :: User state - let user_info_query_resp: UserInfo = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::UserInfo { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(250000000u64), - user_info_query_resp.claimed_amount - ); - assert_eq!(Uint128::from(0u64), user_info_query_resp.delegated_amount); - assert_eq!(true, user_info_query_resp.tokens_withdrawn); -} - -#[cfg(test)] -#[test] -fn test_delegate_astro_to_bootstrap_auction() { - use astroport::asset::AssetInfo; - - let mut app = mock_app(); - let (airdrop_instance, astro_instance, init_msg, token_code_id) = init_contracts(&mut app); - - let owner = Addr::unchecked(init_msg.owner.clone().unwrap()); - - // mint ASTRO for to Owner - mint_some_astro( - &mut app, - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_instance.clone(), - Uint128::from(100_000_000_000u64), - init_msg.owner.clone().unwrap(), - ); - - // Set ASTRO airdrop incentives - app.execute_contract( - Addr::unchecked(init_msg.owner.clone().unwrap()), - astro_instance.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(100_000_000_000u64), - contract: airdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - let pair_contract = Box::new( - ContractWrapper::new( - astroport_pair::contract::execute, - astroport_pair::contract::instantiate, - astroport_pair::contract::query, - ) - .with_reply(astroport_pair::contract::reply), - ); - - let pair_code_id = app.store_code(pair_contract); - - let init_pair_msg = astroport::pair::InstantiateMsg { - asset_infos: [ - AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - AssetInfo::Token { - contract_addr: astro_instance.clone(), - }, - ], - factory_addr: Addr::unchecked("factory_addr").to_string(), - init_params: None, - token_code_id, - }; - let pair_instance = app - .instantiate_contract( - pair_code_id, - owner.clone(), - &init_pair_msg, - &[], - String::from("pair"), - None, - ) - .unwrap(); - - // Initialize Bootstrap Auction contract - let auction_contract = Box::new(ContractWrapper::new( - astroport_auction::contract::execute, - astroport_auction::contract::instantiate, - astroport_auction::contract::query, - )); - let auction_contract_code_id = app.store_code(auction_contract); - let auction_init_msg = astroport_periphery::auction::InstantiateMsg { - owner: init_msg.owner.clone(), - astro_token_address: astro_instance.clone().to_string(), - airdrop_contract_address: airdrop_instance.clone().to_string(), - lockdrop_contract_address: "lockdrop_contract_address".to_string(), - lp_tokens_vesting_duration: 2592000u64, - init_timestamp: 1571897419u64, - deposit_window: 2592000u64, - withdrawal_window: 1592000u64, - }; - - let auction_contract_instance = app - .instantiate_contract( - auction_contract_code_id, - Addr::unchecked(init_msg.owner.clone().unwrap()), - &auction_init_msg, - &[], - String::from("ASTRO"), - None, - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - auction_contract_instance.clone(), - &AuctionExecuteMsg::UpdateConfig { - new_config: UpdateConfigMsg { - astro_ust_pair_address: Some(pair_instance.to_string()), - owner: None, - generator_contract: None, - }, - }, - &[], - ) - .unwrap(); - - let merkle_roots = - vec!["cdcdfad1c342f5f55a2639dcae7321a64cd000807fa24c2c4ddaa944fd52d34e".to_string()]; - - let update_msg = ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: Some(auction_contract_instance.to_string()), - merkle_roots: Some(merkle_roots.clone()), - from_timestamp: None, - to_timestamp: None, - }; - - // Update Config :: should be a success - app.execute_contract(owner.clone(), airdrop_instance.clone(), &update_msg, &[]) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config and make sure all fields are updated - assert_eq!(init_msg.owner.clone().unwrap(), resp.owner); - assert_eq!(merkle_roots, resp.merkle_roots); - assert_eq!(init_msg.from_timestamp.unwrap(), resp.from_timestamp); - assert_eq!(init_msg.to_timestamp, resp.to_timestamp); - - // Update Block to test successful claim - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1571897424) - }); - - // ################################ - // TERRA USER :: Claims not allowed. ASTRO Rewards will Not be transferred to the user - // ################################ - - let claim_msg = ExecuteMsg::Claim { - claim_amount: Uint128::from(250000000 as u64), - merkle_proof: vec![ - "7719b79a65e5aa0bbfd144cf5373138402ab1c374d9049e490b5b61c23d90065".to_string(), - "60368f2058e0fb961a7721a241f9b973c3dd6c57e10a627071cd81abca6aa490".to_string(), - ], - root_index: 0, - }; - - // **** User should successfully claim the Airdrop **** - - // Should be a success - let success_ = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &claim_msg, - &[], - ) - .unwrap(); - - assert_eq!( - success_.events[1].attributes[1], - attr("action", "handle_claim") - ); - assert_eq!( - success_.events[1].attributes[2], - attr("addr", "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp") - ); - assert_eq!( - success_.events[1].attributes[3], - attr("airdrop", "250000000") - ); - - // **** "Total amount being delegated for bootstrap auction cannot exceed your claimable airdrop balance" Error should be returned **** - - let claim_f = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &ExecuteMsg::DelegateAstroToBootstrapAuction { - amount_to_delegate: Uint128::from(250000001u64), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - claim_f.root_cause().to_string(), - "Generic error: Total amount being delegated for bootstrap auction cannot exceed your claimable airdrop balance" - ); - - // **** Should successfully delegate ASTRO **** - - let delegation_res = app - .execute_contract( - Addr::unchecked("terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string()), - airdrop_instance.clone(), - &ExecuteMsg::DelegateAstroToBootstrapAuction { - amount_to_delegate: Uint128::from(250000000u64), - }, - &[], - ) - .unwrap(); - assert_eq!( - delegation_res.events[1].attributes[1], - attr("action", "delegate_astro_to_bootstrap_auction") - ); - assert_eq!( - delegation_res.events[1].attributes[2], - attr("user", "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp") - ); - assert_eq!( - delegation_res.events[1].attributes[3], - attr("amount_delegated", "250000000") - ); - - // Check :: Airdrop :: User state - let user_info_query_resp: UserInfo = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &QueryMsg::UserInfo { - address: "terra17lmam6zguazs5q5u6z5mmx76uj63gldnse2pdp".to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(250000000u64), - user_info_query_resp.claimed_amount - ); - assert_eq!( - Uint128::from(250000000u64), - user_info_query_resp.delegated_amount - ); - assert_eq!(false, user_info_query_resp.tokens_withdrawn); - - // Check :: Airdrop :: Contract state - let state_query_resp: State = app - .wrap() - .query_wasm_smart(&airdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(100_000_000_000u64), - state_query_resp.total_airdrop_size - ); - assert_eq!( - Uint128::from(250000000u64), - state_query_resp.total_delegated_amount - ); - assert_eq!( - Uint128::from(99750000000u64), - state_query_resp.unclaimed_tokens - ); -} diff --git a/contracts/auction/Cargo.toml b/contracts/auction/Cargo.toml index e9aeebfc..2a041765 100644 --- a/contracts/auction/Cargo.toml +++ b/contracts/auction/Cargo.toml @@ -44,5 +44,4 @@ astroport-vesting = { git = "https://github.com/astroport-fi/astroport-core.git" astroport-generator = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" } astroport-whitelist = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" } astroport-factory = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" } -astroport-airdrop = { path = "../airdrop" } astroport-lockdrop = { path = "../lockdrop" } diff --git a/contracts/auction/tests/integration.rs b/contracts/auction/tests/integration.rs deleted file mode 100644 index 50217933..00000000 --- a/contracts/auction/tests/integration.rs +++ /dev/null @@ -1,3045 +0,0 @@ -use astroport::asset::{AssetInfo, PairInfo}; -use astroport::factory::{ - ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, PairConfig, PairType, - QueryMsg as FactoryQueryMsg, -}; -use astroport::generator::ExecuteMsg as GeneratorExecuteMsg; -use astroport_periphery::auction::{ - Config, Cw20HookMsg, ExecuteMsg, InstantiateMsg, QueryMsg, State, UpdateConfigMsg, - UserInfoResponse, -}; - -use cosmwasm_std::{attr, to_binary, Addr, Binary, Coin, Timestamp, Uint128, Uint64}; -use cw20::Cw20ExecuteMsg; -use cw_multi_test::{App, ContractWrapper, Executor}; - -const OWNER: &str = "owner"; - -struct PoolWithProxy { - pool: (String, Uint128), - proxy: Option, -} - -fn mock_app(owner: Addr, coins: Vec) -> App { - App::new(|router, _, storage| { - // initialization moved to App construction - router.bank.init_balance(storage, &owner, coins).unwrap(); - }) -} - -fn validate_and_send_funds(router: &mut App, sender: &Addr, recipient: &Addr, funds: Vec) { - for fund in funds.clone() { - // we cannot transfer zero coins - if !fund.amount.is_zero() { - router - .send_tokens(sender.clone(), recipient.clone(), &[fund]) - .unwrap(); - } - } -} - -fn register_lp_tokens_in_generator( - app: &mut App, - generator_instance: &Addr, - pools_with_proxy: Vec, -) { - let pools: Vec<(String, Uint128)> = pools_with_proxy.iter().map(|p| p.pool.clone()).collect(); - - app.execute_contract( - Addr::unchecked(OWNER), - generator_instance.clone(), - &GeneratorExecuteMsg::SetupPools { pools }, - &[], - ) - .unwrap(); - - for pool_with_proxy in &pools_with_proxy { - if let Some(proxy) = &pool_with_proxy.proxy { - app.execute_contract( - Addr::unchecked(OWNER), - generator_instance.clone(), - &GeneratorExecuteMsg::MoveToProxy { - lp_token: pool_with_proxy.pool.0.clone(), - proxy: proxy.to_string(), - }, - &[], - ) - .unwrap(); - } - } -} - -fn create_pair( - app: &mut App, - factory: &Addr, - pair_type: Option, - init_param: Option, - assets: [AssetInfo; 2], -) -> (Addr, Addr) { - app.execute_contract( - Addr::unchecked(OWNER), - factory.clone(), - &FactoryExecuteMsg::CreatePair { - pair_type: pair_type.unwrap_or_else(|| PairType::Xyk {}), - asset_infos: assets.clone(), - init_params: init_param, - }, - &[], - ) - .unwrap(); - - let res: PairInfo = app - .wrap() - .query_wasm_smart( - factory, - &FactoryQueryMsg::Pair { - asset_infos: assets, - }, - ) - .unwrap(); - - (res.contract_addr, res.liquidity_token) -} - -fn store_whitelist_code(app: &mut App) -> u64 { - let whitelist_contract = Box::new(ContractWrapper::new_with_empty( - astroport_whitelist::contract::execute, - astroport_whitelist::contract::instantiate, - astroport_whitelist::contract::query, - )); - - app.store_code(whitelist_contract) -} - -// Instantiate ASTRO Token Contract -fn instantiate_astro_token(app: &mut App, owner: Addr) -> Addr { - let astro_token_contract = Box::new(ContractWrapper::new( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let astro_token_code_id = app.store_code(astro_token_contract); - - let msg = astroport::token::InstantiateMsg { - name: String::from("Astro token"), - symbol: String::from("ASTRO"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }; - - app.instantiate_contract( - astro_token_code_id, - owner, - &msg, - &[], - String::from("ASTRO"), - None, - ) - .unwrap() -} - -// Instantiate AUCTION Contract -fn instantiate_auction_contract( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, - airdrop_instance: Addr, - lockdrop_instance: Addr, - pair_instance: Addr, -) -> (Addr, InstantiateMsg) { - let auction_contract = Box::new(ContractWrapper::new( - astroport_auction::contract::execute, - astroport_auction::contract::instantiate, - astroport_auction::contract::query, - )); - - let auction_code_id = app.store_code(auction_contract); - - let auction_instantiate_msg = astroport_periphery::auction::InstantiateMsg { - owner: Some(owner.to_string()), - astro_token_address: astro_token_instance.clone().into_string(), - airdrop_contract_address: airdrop_instance.to_string(), - lockdrop_contract_address: lockdrop_instance.to_string(), - lp_tokens_vesting_duration: 7776000u64, - init_timestamp: 1_000_00, - deposit_window: 100_000_00, - withdrawal_window: 5_000_00, - }; - - // Init contract - let auction_instance = app - .instantiate_contract( - auction_code_id, - owner.clone(), - &auction_instantiate_msg, - &[], - "auction", - None, - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - auction_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: UpdateConfigMsg { - astro_ust_pair_address: Some(pair_instance.to_string()), - owner: None, - generator_contract: None, - }, - }, - &[], - ) - .unwrap(); - (auction_instance, auction_instantiate_msg) -} - -fn init_auction_astro_contracts(app: &mut App) -> (Addr, Addr, Addr, Addr, InstantiateMsg) { - let owner = Addr::unchecked("contract_owner"); - let astro_token_instance = instantiate_astro_token(app, owner.clone()); - - // Instantiate LP Pair & Airdrop / Lockdrop Contracts - let (pair_instance, _, _, _) = - instantiate_pair(app, owner.clone(), astro_token_instance.clone()); - let (airdrop_instance, lockdrop_instance) = - instantiate_airdrop_lockdrop_contracts(app, owner.clone(), astro_token_instance.clone()); - - // Instantiate Auction Contract - let (auction_instance, auction_instantiate_msg) = instantiate_auction_contract( - app, - owner, - astro_token_instance.clone(), - airdrop_instance.clone(), - lockdrop_instance.clone(), - pair_instance, - ); - - ( - airdrop_instance, - lockdrop_instance, - auction_instance, - astro_token_instance, - auction_instantiate_msg, - ) -} - -// Initiates Auction, Astro token, Airdrop, Lockdrop and Astroport Pair contracts -fn init_all_contracts( - app: &mut App, -) -> (Addr, Addr, Addr, Addr, Addr, Addr, InstantiateMsg, u64, u64) { - let owner = Addr::unchecked(OWNER); - let astro_token_instance = instantiate_astro_token(app, owner.clone()); - - // Instantiate LP Pair & Airdrop / Lockdrop Contracts - let (pair_instance, lp_token_instance, lp_token_code_id, pair_code_id) = - instantiate_pair(app, owner.clone(), astro_token_instance.clone()); - let (airdrop_instance, lockdrop_instance) = - instantiate_airdrop_lockdrop_contracts(app, owner.clone(), astro_token_instance.clone()); - - // Instantiate Auction Contract - let (auction_instance, auction_instantiate_msg) = instantiate_auction_contract( - app, - owner.clone(), - astro_token_instance.clone(), - airdrop_instance.clone(), - lockdrop_instance.clone(), - pair_instance.clone(), - ); - - // Update Airdrop / Lockdrop Configs - app.execute_contract( - owner.clone(), - airdrop_instance.clone(), - &astroport_periphery::airdrop::ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: Some(auction_instance.to_string()), - merkle_roots: None, - from_timestamp: None, - to_timestamp: None, - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner, - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::UpdateConfig { - new_config: astroport_periphery::lockdrop::UpdateConfigMsg { - auction_contract_address: Some(auction_instance.to_string()), - generator_address: None, - astro_token_address: None, - }, - }, - &[], - ) - .unwrap(); - - ( - auction_instance, - astro_token_instance, - airdrop_instance, - lockdrop_instance, - pair_instance, - lp_token_instance, - auction_instantiate_msg, - lp_token_code_id, - pair_code_id, - ) -} - -// Initiates Astroport Pair for ASTRO-UST Pool -fn instantiate_pair( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, -) -> (Addr, Addr, u64, u64) { - let lp_token_contract = Box::new(ContractWrapper::new( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let pair_contract = Box::new( - ContractWrapper::new( - astroport_pair::contract::execute, - astroport_pair::contract::instantiate, - astroport_pair::contract::query, - ) - .with_reply(astroport_pair::contract::reply), - ); - - let lp_token_code_id = app.store_code(lp_token_contract); - let pair_code_id = app.store_code(pair_contract); - - let msg = astroport::pair::InstantiateMsg { - asset_infos: [ - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - astroport::asset::AssetInfo::Token { - contract_addr: astro_token_instance, - }, - ], - token_code_id: lp_token_code_id, - init_params: None, - factory_addr: Addr::unchecked("factory").to_string(), - }; - - let pair_instance = app - .instantiate_contract( - pair_code_id, - owner.clone(), - &msg, - &[], - String::from("PAIR"), - None, - ) - .unwrap(); - - let resp: astroport::asset::PairInfo = app - .wrap() - .query_wasm_smart(&pair_instance, &astroport::pair::QueryMsg::Pair {}) - .unwrap(); - let lp_token_instance = resp.liquidity_token; - - ( - pair_instance, - lp_token_instance, - lp_token_code_id, - pair_code_id, - ) -} - -// Initiates Airdrop and lockdrop contracts -fn instantiate_airdrop_lockdrop_contracts( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, -) -> (Addr, Addr) { - let airdrop_contract = Box::new(ContractWrapper::new( - astroport_airdrop::contract::execute, - astroport_airdrop::contract::instantiate, - astroport_airdrop::contract::query, - )); - - let lockdrop_contract = Box::new(ContractWrapper::new( - astroport_lockdrop::contract::execute, - astroport_lockdrop::contract::instantiate, - astroport_lockdrop::contract::query, - )); - - let airdrop_code_id = app.store_code(airdrop_contract); - let lockdrop_code_id = app.store_code(lockdrop_contract); - - let airdrop_msg = astroport_periphery::airdrop::InstantiateMsg { - owner: Some(owner.clone().to_string()), - astro_token_address: astro_token_instance.clone().into_string(), - merkle_roots: Some(vec!["merkle_roots".to_string()]), - from_timestamp: Some(1_000_00), - to_timestamp: 100_000_00, - }; - - let lockdrop_msg = astroport_periphery::lockdrop::InstantiateMsg { - owner: Some(owner.to_string()), - init_timestamp: 1_000_00, - deposit_window: 100_000_00, - withdrawal_window: 5_000_00, - weekly_multiplier: 3, - weekly_divider: 51, - min_lock_duration: 1u64, - max_lock_duration: 52u64, - max_positions_per_user: 24, - }; - - let airdrop_instance = app - .instantiate_contract( - airdrop_code_id, - owner.clone(), - &airdrop_msg, - &[], - String::from("airdrop_instance"), - None, - ) - .unwrap(); - - // mint ASTRO for to Owner - mint_some_astro( - app, - Addr::unchecked(owner.clone()), - astro_token_instance.clone(), - Uint128::from(100_000_000_000u64), - owner.clone().to_string(), - ); - - // Set ASTRO airdrop incentives - app.execute_contract( - Addr::unchecked(owner.clone()), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(100_000_000_000u64), - contract: airdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - // open claim period for successful deposit - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(900_00) - }); - - let lockdrop_instance = app - .instantiate_contract( - lockdrop_code_id, - owner.clone(), - &lockdrop_msg, - &[], - String::from("lockdrop_instance"), - None, - ) - .unwrap(); - - mint_some_astro( - app, - owner.clone(), - astro_token_instance.clone(), - Uint128::new(100_000_00u128), - owner.to_string(), - ); - app.execute_contract( - owner.clone(), - astro_token_instance.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: lockdrop_instance.clone().to_string(), - amount: Uint128::new(900_000_000_000), - expires: None, - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::UpdateConfig { - new_config: astroport_periphery::lockdrop::UpdateConfigMsg { - astro_token_address: Some(astro_token_instance.clone().into_string()), - auction_contract_address: None, - generator_address: None, - }, - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - astro_token_instance, - &Cw20ExecuteMsg::Send { - amount: Uint128::from(100_000_00u64), - contract: lockdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - (airdrop_instance, lockdrop_instance) -} - -fn store_factory_code(app: &mut App) -> u64 { - let factory_contract = Box::new( - ContractWrapper::new_with_empty( - astroport_factory::contract::execute, - astroport_factory::contract::instantiate, - astroport_factory::contract::query, - ) - .with_reply_empty(astroport_factory::contract::reply), - ); - - app.store_code(factory_contract) -} - -fn instantiate_factory( - app: &mut App, - factory_code_id: u64, - token_code_id: u64, - pair_code_id: u64, - pair_stable_code_id: Option, -) -> Addr { - let mut msg = FactoryInstantiateMsg { - pair_configs: vec![PairConfig { - code_id: pair_code_id, - pair_type: PairType::Xyk {}, - total_fee_bps: 100, - maker_fee_bps: 10, - is_disabled: false, - is_generator_disabled: false, - }], - token_code_id, - fee_address: None, - generator_address: None, - owner: String::from("owner"), - whitelist_code_id: 0, - }; - - if let Some(pair_stable_code_id) = pair_stable_code_id { - msg.pair_configs.push(PairConfig { - code_id: pair_stable_code_id, - pair_type: PairType::Stable {}, - total_fee_bps: 100, - maker_fee_bps: 10, - is_disabled: false, - is_generator_disabled: false, - }); - } - - app.instantiate_contract( - factory_code_id, - Addr::unchecked("owner"), - &msg, - &[], - "Factory", - None, - ) - .unwrap() -} - -// Instantiate Astroport's generator and vesting contracts -fn instantiate_generator_and_vesting( - mut app: &mut App, - owner: Addr, - astro_token_instance: Addr, - lp_token_instance: Addr, - token_code_id: u64, - pair_code_id: u64, -) -> (Addr, Addr) { - // Vesting - let vesting_contract = Box::new(ContractWrapper::new( - astroport_vesting::contract::execute, - astroport_vesting::contract::instantiate, - astroport_vesting::contract::query, - )); - let vesting_code_id = app.store_code(vesting_contract); - - let init_msg = astroport::vesting::InstantiateMsg { - owner: owner.to_string(), - token_addr: astro_token_instance.clone().to_string(), - }; - - let vesting_instance = app - .instantiate_contract( - vesting_code_id, - owner.clone(), - &init_msg, - &[], - "Vesting", - None, - ) - .unwrap(); - - mint_some_astro( - &mut app, - owner.clone(), - astro_token_instance.clone(), - Uint128::new(900_000_000_000), - owner.to_string(), - ); - app.execute_contract( - owner.clone(), - astro_token_instance.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: vesting_instance.clone().to_string(), - amount: Uint128::new(900_000_000_000), - expires: None, - }, - &[], - ) - .unwrap(); - - // Generator - let generator_contract = Box::new( - ContractWrapper::new( - astroport_generator::contract::execute, - astroport_generator::contract::instantiate, - astroport_generator::contract::query, - ) - .with_reply(astroport_generator::contract::reply), - ); - - let generator_code_id = app.store_code(generator_contract); - let whitelist_code_id = store_whitelist_code(&mut app); - let factory_code_id = store_factory_code(&mut app); - - let factory_instance = - instantiate_factory(&mut app, factory_code_id, token_code_id, pair_code_id, None); - - let init_msg = astroport::generator::InstantiateMsg { - allowed_reward_proxies: vec![], - start_block: Uint64::from(app.block_info().height), - astro_token: astro_token_instance.to_string(), - tokens_per_block: Uint128::from(0u128), - vesting_contract: vesting_instance.clone().to_string(), - owner: owner.to_string(), - factory: factory_instance.to_string(), - generator_controller: None, - voting_escrow: None, - guardian: None, - whitelist_code_id, - }; - - let generator_instance = app - .instantiate_contract( - generator_code_id, - owner.clone(), - &init_msg, - &[], - "Guage", - None, - ) - .unwrap(); - - let tokens_per_block = Uint128::new(10_000000); - - let msg = astroport::generator::ExecuteMsg::SetTokensPerBlock { - amount: tokens_per_block, - }; - app.execute_contract(owner.clone(), generator_instance.clone(), &msg, &[]) - .unwrap(); - - let msg = astroport::generator::QueryMsg::Config {}; - let res: astroport::generator::Config = app - .wrap() - .query_wasm_smart(&generator_instance, &msg) - .unwrap(); - assert_eq!(res.tokens_per_block, tokens_per_block); - - // vesting to generator: - - let current_block = app.block_info(); - - let amount = Uint128::new(630720000000); - - let msg = Cw20ExecuteMsg::Send { - contract: vesting_instance.to_string(), - amount, - msg: to_binary(&astroport::vesting::Cw20HookMsg::RegisterVestingAccounts { - vesting_accounts: vec![astroport::vesting::VestingAccount { - address: generator_instance.to_string(), - schedules: vec![astroport::vesting::VestingSchedule { - start_point: astroport::vesting::VestingSchedulePoint { - time: current_block.time.seconds(), - amount, - }, - end_point: None, - }], - }], - }) - .unwrap(), - }; - - app.execute_contract(owner.clone(), astro_token_instance.clone(), &msg, &[]) - .unwrap(); - - let (_, _) = create_pair( - &mut app, - &factory_instance, - None, - None, - [ - AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - AssetInfo::Token { - contract_addr: astro_token_instance.clone(), - }, - ], - ); - - // Set pool alloc points - register_lp_tokens_in_generator( - &mut app, - &generator_instance, - vec![PoolWithProxy { - pool: (lp_token_instance.to_string(), Uint128::new(10)), - proxy: None, - }], - ); - - (generator_instance, vesting_instance) -} - -// Mints some ASTRO to "to" recipient -fn mint_some_astro( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, - amount: Uint128, - to: String, -) { - let msg = cw20::Cw20ExecuteMsg::Mint { - recipient: to.clone(), - amount: amount, - }; - let res = app - .execute_contract(owner.clone(), astro_token_instance.clone(), &msg, &[]) - .unwrap(); - assert_eq!(res.events[1].attributes[1], attr("action", "mint")); - assert_eq!(res.events[1].attributes[2], attr("to", to)); - assert_eq!(res.events[1].attributes[3], attr("amount", amount)); -} - -// Makes ASTRO & UST deposits into Auction contract -fn make_astro_ust_deposits( - mut app: &mut App, - auction_instance: Addr, - auction_init_msg: InstantiateMsg, - astro_token_instance: Addr, -) -> (Addr, Addr, Addr) { - let user1_address = Addr::unchecked("user1"); - let user2_address = Addr::unchecked("user2"); - let user3_address = Addr::unchecked("user3"); - - // open claim period for successful deposit - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1_000_01) - }); - - // ###### SUCCESS :: ASTRO Successfully deposited ###### - app.execute_contract( - Addr::unchecked(auction_init_msg.lockdrop_contract_address.clone()), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(100000000), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: user1_address.to_string(), - }) - .unwrap(), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(auction_init_msg.lockdrop_contract_address.clone()), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(65435340), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: user2_address.to_string(), - }) - .unwrap(), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(auction_init_msg.lockdrop_contract_address.clone()), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(76754654), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: user3_address.to_string(), - }) - .unwrap(), - }, - &[], - ) - .unwrap(); - - // Set user balances - validate_and_send_funds( - &mut app, - &Addr::unchecked(OWNER), - &user1_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(20000000u128), - }], - ); - - validate_and_send_funds( - &mut app, - &Addr::unchecked(OWNER), - &user2_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(5435435u128), - }], - ); - - validate_and_send_funds( - &mut app, - &Addr::unchecked(OWNER), - &user3_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(43534534u128), - }], - ); - - // deposit UST Msg - let deposit_ust_msg = &ExecuteMsg::DepositUst {}; - - // ###### SUCCESS :: UST Successfully deposited ###### - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(432423u128), - }], - ) - .unwrap(); - - app.execute_contract( - user2_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(454353u128), - }], - ) - .unwrap(); - - app.execute_contract( - user3_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(5643543u128), - }], - ) - .unwrap(); - - (user1_address, user2_address, user3_address) -} - -#[test] -fn proper_initialization_only_auction_astro() { - let owner = Addr::unchecked(OWNER); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (_, _, auction_instance, _, auction_init_msg) = init_auction_astro_contracts(&mut app); - - let resp: Config = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config - assert_eq!(Addr::unchecked(auction_init_msg.owner.unwrap()), resp.owner); - assert_eq!( - auction_init_msg.astro_token_address, - resp.astro_token_address - ); - assert_eq!( - auction_init_msg.airdrop_contract_address, - resp.airdrop_contract_address - ); - assert_eq!( - auction_init_msg.lockdrop_contract_address, - resp.lockdrop_contract_address - ); - assert_eq!(auction_init_msg.init_timestamp, resp.init_timestamp); - assert_eq!(auction_init_msg.deposit_window, resp.deposit_window); - assert_eq!(auction_init_msg.withdrawal_window, resp.withdrawal_window); - - // Check state - let resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - - assert!(resp.total_astro_delegated.is_zero()); - assert!(resp.total_ust_delegated.is_zero()); - assert!(resp.lp_shares_minted.is_none()); - assert!(!resp.is_lp_staked); - assert_eq!(0u64, resp.pool_init_timestamp); - assert!(resp.generator_astro_per_share.is_zero()); -} - -#[test] -fn proper_initialization_all_contracts() { - let owner = Addr::unchecked(OWNER); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (auction_instance, _, _, _, _, _, auction_init_msg, _, _) = init_all_contracts(&mut app); - - let resp: Config = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config - assert_eq!(auction_init_msg.owner, Some(resp.owner.to_string())); - assert_eq!( - auction_init_msg.astro_token_address, - resp.astro_token_address - ); - assert_eq!( - auction_init_msg.airdrop_contract_address, - resp.airdrop_contract_address - ); - assert_eq!( - auction_init_msg.lockdrop_contract_address, - resp.lockdrop_contract_address - ); - assert_eq!(auction_init_msg.init_timestamp, resp.init_timestamp); - assert_eq!(auction_init_msg.deposit_window, resp.deposit_window); - assert_eq!(auction_init_msg.withdrawal_window, resp.withdrawal_window); - - // Check state - let resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - - assert!(resp.total_astro_delegated.is_zero()); - assert!(resp.total_ust_delegated.is_zero()); - assert!(resp.lp_shares_minted.is_none()); - assert!(!resp.is_lp_staked); - assert_eq!(0u64, resp.pool_init_timestamp); - assert!(resp.generator_astro_per_share.is_zero()); -} - -#[test] -fn test_delegate_astro_tokens_from_airdrop() { - let owner = Addr::unchecked(OWNER); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (airdrop_instance, _, auction_instance, astro_token_instance, auction_init_msg) = - init_auction_astro_contracts(&mut app); - - // mint ASTRO for to Airdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - airdrop_instance.to_string(), - ); - - // mint ASTRO for to Wrong Airdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - "not_airdrop_instance".to_string(), - ); - - // deposit ASTRO Msg - let send_cw20_msg = &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(100000000), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: "airdrop_recipient".to_string(), - }) - .unwrap(), - }; - - // ###### ERROR :: Unauthorized ###### - let mut err = app - .execute_contract( - Addr::unchecked("not_airdrop_instance"), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### ERROR :: Amount must be greater than 0 ###### - err = app - .execute_contract( - airdrop_instance.clone(), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(0), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: "airdrop_recipient".to_string(), - }) - .unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Invalid zero amount"); - - // ###### ERROR :: Deposit window closed ###### - err = app - .execute_contract( - airdrop_instance.clone(), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); - - // open claim period for successful deposit - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1_000_01) - }); - - // ###### SUCCESS :: ASTRO Successfully deposited ###### - app.execute_contract( - airdrop_instance.clone(), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap(); - // Check state response - let state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(100000000u64), - state_resp.total_astro_delegated - ); - assert_eq!(Uint128::from(0u64), state_resp.total_ust_delegated); - assert_eq!(None, state_resp.lp_shares_minted); - assert!(!state_resp.is_lp_staked); - assert!(state_resp.generator_astro_per_share.is_zero()); - // Check user response - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: "airdrop_recipient".to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100000000u64), user_resp.astro_delegated); - assert_eq!(Uint128::from(0u64), user_resp.ust_delegated); - assert_eq!(None, user_resp.lp_shares); - assert_eq!(None, user_resp.withdrawable_lp_shares); - assert_eq!(None, user_resp.auction_incentive_amount); - - // ###### SUCCESS :: ASTRO Successfully deposited again ###### - app.execute_contract( - airdrop_instance.clone(), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap(); - // Check state response - let state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(200000000u64), - state_resp.total_astro_delegated - ); - assert_eq!(Uint128::from(0u64), state_resp.total_ust_delegated); - assert_eq!(None, state_resp.lp_shares_minted); - assert!(!state_resp.is_lp_staked); - assert!(state_resp.generator_astro_per_share.is_zero()); - // Check user response - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: "airdrop_recipient".to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(200000000u64), user_resp.astro_delegated); - assert_eq!(Uint128::from(0u64), user_resp.ust_delegated); - assert_eq!(None, user_resp.lp_shares); - assert_eq!(None, user_resp.withdrawable_lp_shares); - assert_eq!(None, user_resp.auction_incentive_amount); - - // ###### ERROR :: Deposit window closed ###### - - // finish claim period for deposit failure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10100001) - }); - err = app - .execute_contract( - airdrop_instance, - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); -} - -#[test] -fn test_delegate_astro_tokens_from_lockdrop() { - let owner = Addr::unchecked(OWNER); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (_, lockdrop_instance, auction_instance, astro_token_instance, auction_init_msg) = - init_auction_astro_contracts(&mut app); - - // mint ASTRO for to Lockdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - lockdrop_instance.to_string(), - ); - - // mint ASTRO for to Wrong Lockdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - "not_lockdrop_instance".to_string(), - ); - - // deposit ASTRO Msg - let send_cw20_msg = &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(100000000), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: "lockdrop_participant".to_string(), - }) - .unwrap(), - }; - - // ###### ERROR :: Unauthorized ###### - let mut err = app - .execute_contract( - Addr::unchecked("not_lockdrop_instance"), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### ERROR :: Amount must be greater than 0 ###### - err = app - .execute_contract( - lockdrop_instance.clone(), - astro_token_instance.clone(), - &Cw20ExecuteMsg::Send { - contract: auction_instance.clone().to_string(), - amount: Uint128::new(0), - msg: to_binary(&Cw20HookMsg::DelegateAstroTokens { - user_address: "lockdrop_participant".to_string(), - }) - .unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Invalid zero amount"); - - // ###### ERROR :: Deposit window closed ###### - err = app - .execute_contract( - lockdrop_instance.clone(), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); - - // open claim period for successful deposit - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1_000_01) - }); - - // ###### SUCCESS :: ASTRO Successfully deposited ###### - app.execute_contract( - lockdrop_instance.clone(), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap(); - // Check state response - let state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(100000000u64), - state_resp.total_astro_delegated - ); - - // Check user response - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: "lockdrop_participant".to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100000000u64), user_resp.astro_delegated); - assert_eq!(Uint128::from(0u64), user_resp.ust_delegated); - - // ###### SUCCESS :: ASTRO Successfully deposited again ###### - app.execute_contract( - lockdrop_instance.clone(), - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap(); - // Check state response - let state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(200000000u64), - state_resp.total_astro_delegated - ); - assert_eq!(Uint128::from(0u64), state_resp.total_ust_delegated); - - // Check user response - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: "lockdrop_participant".to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(200000000u64), user_resp.astro_delegated); - - // ###### ERROR :: Deposit window closed ###### - - // finish claim period for deposit failure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10100001) - }); - err = app - .execute_contract( - lockdrop_instance, - astro_token_instance.clone(), - &send_cw20_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); -} - -#[test] -fn test_update_config() { - let owner = Addr::unchecked("owner"); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (_, _, auction_instance, _, auction_init_msg) = init_auction_astro_contracts(&mut app); - - let update_msg = UpdateConfigMsg { - owner: Some("new_owner".to_string()), - astro_ust_pair_address: None, - generator_contract: Some("generator_contract".to_string()), - }; - - // ###### ERROR :: Only owner can update configuration ###### - let err = app - .execute_contract( - Addr::unchecked("wrong_owner"), - auction_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Only owner can update configuration" - ); - - // ###### SUCCESS :: Should have successfully updated ###### - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.unwrap()), - auction_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::Config {}) - .unwrap(); - // Check config - assert_eq!(update_msg.clone().owner.unwrap(), resp.owner); - assert_eq!( - update_msg.clone().generator_contract.unwrap(), - resp.generator_contract.unwrap() - ); -} - -#[test] -fn test_deposit_ust() { - let owner = Addr::unchecked("owner"); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (_, _, auction_instance, _, _) = init_auction_astro_contracts(&mut app); - let user_address = Addr::unchecked("user"); - - // Set user balances - validate_and_send_funds( - &mut app, - &owner, - &user_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(20_000_000u128), - }], - ); - - // deposit UST Msg - let deposit_ust_msg = &ExecuteMsg::DepositUst {}; - let coins = [Coin { - denom: "uusd".to_string(), - amount: Uint128::from(10000u128), - }]; - - // ###### ERROR :: Deposit window closed ###### - let mut err = app - .execute_contract( - user_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); - - // open claim period for successful deposit - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1_000_01) - }); - - // ###### ERROR :: Amount must be greater than 0 ###### - err = app - .execute_contract( - user_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(0u128), - }], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Cannot transfer empty coins amount" - ); - - // ###### SUCCESS :: UST Successfully deposited ###### - app.execute_contract( - user_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap(); - // Check state response - let mut state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(00u64), state_resp.total_astro_delegated); - assert_eq!(Uint128::from(10000u64), state_resp.total_ust_delegated); - assert_eq!(None, state_resp.lp_shares_minted); - assert!(!state_resp.is_lp_staked); - - // Check user response - let mut user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: user_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(0u64), user_resp.astro_delegated); - assert_eq!(Uint128::from(10000u64), user_resp.ust_delegated); - assert_eq!(None, user_resp.lp_shares); - assert_eq!(None, user_resp.withdrawable_lp_shares); - assert_eq!(None, user_resp.auction_incentive_amount); - - // ###### SUCCESS :: UST Successfully deposited again ###### - app.execute_contract( - user_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap(); - // Check state response - state_resp = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(00u64), state_resp.total_astro_delegated); - assert_eq!(Uint128::from(20000u64), state_resp.total_ust_delegated); - - // Check user response - user_resp = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: user_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(0u64), user_resp.astro_delegated); - assert_eq!(Uint128::from(20000u64), user_resp.ust_delegated); - - // finish claim period for deposit failure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10100001) - }); - err = app - .execute_contract( - user_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); -} - -#[test] -fn test_withdraw_ust() { - let owner = Addr::unchecked("owner"); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let (_, _, auction_instance, _, _) = init_auction_astro_contracts(&mut app); - let user1_address = Addr::unchecked("user1"); - let user2_address = Addr::unchecked("user2"); - let user3_address = Addr::unchecked("user3"); - - // Set user balances - validate_and_send_funds( - &mut app, - &owner, - &user1_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(20_000_000u128), - }], - ); - - validate_and_send_funds( - &mut app, - &owner, - &user2_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(20_000_000u128), - }], - ); - - validate_and_send_funds( - &mut app, - &owner, - &user3_address, - vec![Coin { - denom: "uusd".to_string(), - amount: Uint128::new(20_000_000u128), - }], - ); - - // deposit UST Msg - let deposit_ust_msg = &ExecuteMsg::DepositUst {}; - let coins = [Coin { - denom: "uusd".to_string(), - amount: Uint128::from(10000u128), - }]; - - // open claim period for successful deposit - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(1_000_01) - }); - - // ###### SUCCESS :: UST Successfully deposited ###### - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap(); - app.execute_contract( - user2_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap(); - app.execute_contract( - user3_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap(); - - // ###### SUCCESS :: UST Successfully withdrawn (when withdrawals allowed) ###### - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(10000u64), - }, - &[], - ) - .unwrap(); - // Check state response - let mut state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(20000u64), state_resp.total_ust_delegated); - - // Check user response - let mut user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(0u64), user_resp.ust_delegated); - - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &deposit_ust_msg, - &coins, - ) - .unwrap(); - - // close deposit window. Max 50% withdrawals allowed now - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10100001) - }); - - // ###### ERROR :: Amount exceeds maximum allowed withdrawal limit of {} ###### - - let mut err = app - .execute_contract( - user1_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(10000u64), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Amount exceeds maximum allowed withdrawal limit of 0.5" - ); - - // ###### SUCCESS :: Withdraw 50% successfully ###### - - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(5000u64), - }, - &[], - ) - .unwrap(); - // Check state response - state_resp = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(25000u64), state_resp.total_ust_delegated); - - // Check user response - user_resp = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(5000u64), user_resp.ust_delegated); - - // ###### ERROR :: Max 1 withdrawal allowed during current window ###### - - err = app - .execute_contract( - user1_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(10u64), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Max 1 withdrawal allowed" - ); - - // 50% of withdrawal window over. Max withdrawal % decreasing linearly now - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10351001) - }); - - // ###### ERROR :: Amount exceeds maximum allowed withdrawal limit of {} ###### - - let mut err = app - .execute_contract( - user2_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(10000u64), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Amount exceeds maximum allowed withdrawal limit of 0.497998" - ); - - // ###### SUCCESS :: Withdraw some UST successfully ###### - - app.execute_contract( - user2_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(2000u64), - }, - &[], - ) - .unwrap(); - // Check state response - state_resp = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(23000u64), state_resp.total_ust_delegated); - - // Check user response - user_resp = app - .wrap() - .query_wasm_smart( - &auction_instance, - &QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(8000u64), user_resp.ust_delegated); - - // ###### ERROR :: Max 1 withdrawal allowed during current window ###### - - err = app - .execute_contract( - user2_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(10u64), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Max 1 withdrawal allowed" - ); - - // finish deposit period for deposit failure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10611001) - }); - - err = app - .execute_contract( - user3_address.clone(), - auction_instance.clone(), - &ExecuteMsg::WithdrawUst { - amount: Uint128::from(10u64), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Amount exceeds maximum allowed withdrawal limit of 0" - ); -} - -#[test] -fn test_add_liquidity_to_astroport_pool() { - let owner = Addr::unchecked("owner"); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let ( - auction_instance, - astro_token_instance, - airdrop_instance, - lockdrop_instance, - pair_instance, - _, - auction_init_msg, - _, - _, - ) = init_all_contracts(&mut app); - - // mint ASTRO to Lockdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - auction_init_msg.lockdrop_contract_address.to_string(), - ); - - let (user1_address, user2_address, user3_address) = make_astro_ust_deposits( - &mut app, - auction_instance.clone(), - auction_init_msg.clone(), - astro_token_instance.clone(), - ); - - // ###### ERROR :: Unauthorized ###### - - let mut err = app - .execute_contract( - Addr::unchecked("not_owner".to_string()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### ERROR :: Deposit/withdrawal windows are still open ###### - - err = app - .execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit/withdrawal windows are still open" - ); - - // finish deposit / withdraw period - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10611001) - }); - - // mint ASTRO to owner - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - lockdrop_instance.to_string(), - ); - - app.execute_contract( - lockdrop_instance.clone(), - astro_token_instance, - &Cw20ExecuteMsg::Send { - amount: Uint128::new(100_000_000000), - contract: auction_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - let success_ = app - .execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap(); - assert_eq!( - success_.events[1].attributes[1], - attr("action", "Auction::ExecuteMsg::AddLiquidityToAstroportPool") - ); - assert_eq!( - success_.events[1].attributes[2], - attr("astro_provided", "242189994") - ); - assert_eq!( - success_.events[1].attributes[3], - attr("ust_provided", "6530319") - ); - - // Auction :: Check state response - let state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(242189994u64), - state_resp.total_astro_delegated - ); - assert_eq!(Uint128::from(6530319u64), state_resp.total_ust_delegated); - assert_eq!( - Some(Uint128::from(39769057u64)), - state_resp.lp_shares_minted - ); - assert!(!state_resp.is_lp_staked); - assert!(state_resp.generator_astro_per_share.is_zero()); - assert_eq!(10611001u64, state_resp.pool_init_timestamp); - - // Astroport Pool :: Check response - let pool_resp: astroport::pair::PoolResponse = app - .wrap() - .query_wasm_smart(&pair_instance, &astroport::pair::QueryMsg::Pool {}) - .unwrap(); - assert_eq!(Uint128::from(39769057u64), pool_resp.total_share); - - // Airdrop :: Check config for claims - let airdrop_config_resp: astroport_periphery::airdrop::Config = app - .wrap() - .query_wasm_smart( - &airdrop_instance, - &astroport_periphery::airdrop::QueryMsg::Config {}, - ) - .unwrap(); - assert_eq!(true, airdrop_config_resp.are_claims_enabled); - - // Lockdrop :: Check state for claims - let lockdrop_config_resp: astroport_periphery::lockdrop::StateResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &astroport_periphery::lockdrop::QueryMsg::State {}, - ) - .unwrap(); - assert_eq!(true, lockdrop_config_resp.are_claims_allowed); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10911001) - }); - - // Auction :: Check user-1 state - let user1info_resp: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100000000u64), user1info_resp.astro_delegated); - assert_eq!(Uint128::from(432423u64), user1info_resp.ust_delegated); - assert_eq!(Some(Uint128::from(9527010u64)), user1info_resp.lp_shares); - assert_eq!( - Some(Uint128::from(367554u64)), - user1info_resp.withdrawable_lp_shares - ); - assert_eq!( - Some(Uint128::from(23955835814u64)), - user1info_resp.auction_incentive_amount - ); - assert!(user1info_resp.generator_astro_debt.is_zero()); - - // Auction :: Check user-2 state - let user2info_resp: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(65435340u64), user2info_resp.astro_delegated); - assert_eq!(Uint128::from(454353u64), user2info_resp.ust_delegated); - assert_eq!(Some(Uint128::from(6755923u64)), user2info_resp.lp_shares); - assert_eq!( - Some(Uint128::from(260645u64)), - user2info_resp.withdrawable_lp_shares - ); - assert_eq!( - Some(Uint128::from(16987888347u64)), - user2info_resp.auction_incentive_amount - ); - - // Auction :: Check user-3 state - let user3info_resp: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user3_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(76754654u64), user3info_resp.astro_delegated); - assert_eq!(Uint128::from(5643543u64), user3info_resp.ust_delegated); - assert_eq!(Some(Uint128::from(23486123u64)), user3info_resp.lp_shares); - assert_eq!( - Some(Uint128::from(906100u64)), - user3info_resp.withdrawable_lp_shares - ); - assert_eq!( - Some(Uint128::from(59056273323u64)), - user3info_resp.auction_incentive_amount - ); - - // ###### ERROR :: Liquidity already added ###### - // user1_address, user2_address, user3_address - err = app - .execute_contract( - Addr::unchecked(auction_init_msg.owner.unwrap()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Liquidity already added" - ); -} - -#[test] -fn test_stake_lp_tokens() { - let owner = Addr::unchecked("owner"); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let ( - auction_instance, - astro_token_instance, - _, - _, - _, - lp_token_instance, - auction_init_msg, - token_code_id, - pair_code_id, - ) = init_all_contracts(&mut app); - - let owner = Addr::unchecked(auction_init_msg.owner.clone().unwrap()); - - // mint ASTRO to Lockdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - auction_init_msg.lockdrop_contract_address.to_string(), - ); - - let (user1_address, user2_address, user3_address) = make_astro_ust_deposits( - &mut app, - auction_instance.clone(), - auction_init_msg.clone(), - astro_token_instance.clone(), - ); - - // ###### Initialize generator and vesting instance ###### - let (generator_instance, _) = instantiate_generator_and_vesting( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - lp_token_instance.clone(), - token_code_id, - pair_code_id, - ); - - let update_msg = UpdateConfigMsg { - owner: None, - astro_ust_pair_address: None, - generator_contract: Some(generator_instance.to_string()), - }; - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap(); - - // finish deposit / withdraw period - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10611001) - }); - - app.execute_contract( - owner.clone(), - astro_token_instance, - &Cw20ExecuteMsg::Send { - amount: Uint128::new(100_000_000000), - contract: auction_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - let _success = app - .execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Unauthorized ###### - - let mut err = app - .execute_contract( - Addr::unchecked("not_owner".to_string()), - auction_instance.clone(), - &ExecuteMsg::StakeLpTokens {}, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### SUCCESS :: Stake successfully ###### - - let success_ = app - .execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::StakeLpTokens {}, - &[], - ) - .unwrap(); - assert_eq!( - success_.events[1].attributes[1], - attr("action", "Auction::ExecuteMsg::StakeLPTokens") - ); - assert_eq!( - success_.events[1].attributes[2], - attr("staked_amount", "39769057") - ); - - // Auction :: Check state response - let state_resp: State = app - .wrap() - .query_wasm_smart(&auction_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!( - Uint128::from(242189994u64), - state_resp.total_astro_delegated - ); - assert_eq!(Uint128::from(6530319u64), state_resp.total_ust_delegated); - assert_eq!( - Some(Uint128::from(39769057u64)), - state_resp.lp_shares_minted - ); - assert!(state_resp.is_lp_staked); - assert_eq!(10611001u64, state_resp.pool_init_timestamp); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10911001) - }); - - // Auction :: Check user-1 state - let user1info_resp: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(100000000u64), user1info_resp.astro_delegated); - assert_eq!(Uint128::from(432423u64), user1info_resp.ust_delegated); - assert_eq!(Some(Uint128::from(9527010u64)), user1info_resp.lp_shares); - assert_eq!(Uint128::from(0u64), user1info_resp.claimed_lp_shares); - assert_eq!( - Some(Uint128::from(367554u64)), - user1info_resp.withdrawable_lp_shares - ); - assert_eq!( - Some(Uint128::from(23955835814u64)), - user1info_resp.auction_incentive_amount - ); - - // Auction :: Check user-2 state - let user2info_resp: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(65435340u64), user2info_resp.astro_delegated); - assert_eq!(Uint128::from(454353u64), user2info_resp.ust_delegated); - assert_eq!(Some(Uint128::from(6755923u64)), user2info_resp.lp_shares); - assert_eq!(Uint128::from(0u64), user2info_resp.claimed_lp_shares); - assert_eq!( - Some(Uint128::from(260645u64)), - user2info_resp.withdrawable_lp_shares - ); - assert_eq!( - Some(Uint128::from(16987888347u64)), - user2info_resp.auction_incentive_amount - ); - - // Auction :: Check user-3 state - let user3info_resp: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user3_address.to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(76754654u64), user3info_resp.astro_delegated); - assert_eq!(Uint128::from(5643543u64), user3info_resp.ust_delegated); - assert_eq!(Some(Uint128::from(23486123u64)), user3info_resp.lp_shares); - assert_eq!(Uint128::from(0u64), user3info_resp.claimed_lp_shares); - assert_eq!( - Some(Uint128::from(906100u64)), - user3info_resp.withdrawable_lp_shares - ); - assert_eq!( - Some(Uint128::from(59056273323u64)), - user3info_resp.auction_incentive_amount - ); - - // ###### ERROR :: Already staked ###### - - err = app - .execute_contract( - Addr::unchecked(auction_init_msg.owner.unwrap()), - auction_instance.clone(), - &ExecuteMsg::StakeLpTokens {}, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Already staked" - ); -} - -#[test] -fn test_claim_rewards() { - let owner = Addr::unchecked("owner"); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000u128), - }, - ], - ); - let ( - auction_instance, - astro_token_instance, - _, - _, - _, - lp_token_instance, - auction_init_msg, - token_code_id, - pair_code_id, - ) = init_all_contracts(&mut app); - - let owner = Addr::unchecked(auction_init_msg.owner.clone().unwrap()); - - let claim_rewards_msg = ExecuteMsg::ClaimRewards { - withdraw_lp_shares: None, - }; - - // mint ASTRO to Lockdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - auction_init_msg.lockdrop_contract_address.to_string(), - ); - - // mint ASTRO to owner - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - owner.to_string(), - ); - - let (user1_address, user2_address, user3_address) = make_astro_ust_deposits( - &mut app, - auction_instance.clone(), - auction_init_msg.clone(), - astro_token_instance.clone(), - ); - - // ###### Initialize generator and vesting instance ###### - let (generator_instance, _) = instantiate_generator_and_vesting( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - lp_token_instance.clone(), - token_code_id, - pair_code_id, - ); - - let update_msg = UpdateConfigMsg { - owner: None, - astro_ust_pair_address: None, - generator_contract: Some(generator_instance.to_string()), - }; - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - astro_token_instance, - &Cw20ExecuteMsg::Send { - amount: Uint128::new(100_000_000000), - contract: auction_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Deposit/withdrawal windows are open ###### - - let mut err = app - .execute_contract( - owner, - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit/withdrawal windows are still open" - ); - - // Astro/USD should be provided to the pool - - err = app - .execute_contract( - user1_address.clone(), - auction_instance.clone(), - &claim_rewards_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Astro/USD should be provided to the pool!" - ); - - // finish deposit / withdraw period - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10611001) - }); - - // ###### ERROR :: Invalid request ###### - - err = app - .execute_contract( - Addr::unchecked("not_user".to_string()), - auction_instance.clone(), - &claim_rewards_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "astroport_periphery::auction::UserInfo not found" - ); - - // ###### Sucess :: Initialize ASTRO-UST Pool ###### - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap(); - - // ###### SUCCESS :: Stake successfully ###### - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.unwrap()), - auction_instance.clone(), - &ExecuteMsg::StakeLpTokens {}, - &[], - ) - .unwrap(); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10911001) - }); - - // ###### SUCCESS :: Successfully claim staking rewards for User-1 ###### - - // Auction :: Check user-1 state (before claim) - let user1info_before_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - - // Auction :: Claim rewards for the user - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &claim_rewards_msg, - &[], - ) - .unwrap(); - - // Auction :: Check user-1 state (After Claim) - let user1info_after_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user1info_before_claim.claimed_lp_shares, - user1info_after_claim.claimed_lp_shares - ); - assert_eq!( - user1info_before_claim.withdrawable_lp_shares, - user1info_after_claim.withdrawable_lp_shares - ); - - // ###### SUCCESS :: Successfully claim staking rewards for User-2 ###### - - // Auction :: Check user-2 state (before claim) - let user2info_before_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - - // Auction :: Claim rewards for the user 2 - app.execute_contract( - user2_address.clone(), - auction_instance.clone(), - &claim_rewards_msg, - &[], - ) - .unwrap(); - - // Auction :: Check user-2 state (After Claim) - let user2info_after_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user2info_before_claim.claimed_lp_shares, - user2info_after_claim.claimed_lp_shares - ); - assert_eq!( - user2info_before_claim.withdrawable_lp_shares, - user2info_after_claim.withdrawable_lp_shares - ); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10991001) - }); - - // ###### SUCCESS :: Successfully claim staking rewards for User-3 ###### - - // Auction :: Check user-3 state (before claim) - let user3info_before_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user3_address.to_string(), - }, - ) - .unwrap(); - - // Auction :: Claim rewards for the user 3 - app.execute_contract( - user3_address.clone(), - auction_instance.clone(), - &claim_rewards_msg, - &[], - ) - .unwrap(); - - // Auction :: Check user-3 state (After Claim) - let user3info_after_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user3_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user3info_before_claim.claimed_lp_shares, - user3info_after_claim.claimed_lp_shares - ); - assert_eq!( - user3info_before_claim.withdrawable_lp_shares, - user3info_after_claim.withdrawable_lp_shares - ); - - // ###### SUCCESS :: Successfully again claim staking rewards for User-1 ###### - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10992001) - }); - - // Auction :: Check user-1 state (before claim) - let user1info_before_claim2: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - - // Auction :: Claim rewards for the user - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &claim_rewards_msg, - &[], - ) - .unwrap(); - - // Auction :: Check user-1 state (After Claim) - let user1info_after_claim2: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user1info_before_claim2.claimed_lp_shares, - user1info_after_claim2.claimed_lp_shares - ); - assert_eq!( - user1info_before_claim2.withdrawable_lp_shares, - user1info_after_claim2.withdrawable_lp_shares - ); -} - -#[test] -fn test_withdraw_unlocked_lp_shares() { - let owner = Addr::unchecked(OWNER); - let mut app = mock_app( - owner.clone(), - vec![ - Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000_000_000_000u128), - }, - Coin { - denom: "uluna".to_string(), - amount: Uint128::new(100_000_000_000_000u128), - }, - ], - ); - let ( - auction_instance, - astro_token_instance, - _, - _, - _, - lp_token_instance, - auction_init_msg, - token_code_id, - pair_code_id, - ) = init_all_contracts(&mut app); - - let owner = Addr::unchecked(auction_init_msg.owner.clone().unwrap()); - - let withdraw_lp_msg = ExecuteMsg::ClaimRewards { - withdraw_lp_shares: Some(Uint128::new(1)), - }; - - // mint ASTRO to Lockdrop Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - auction_init_msg.lockdrop_contract_address.to_string(), - ); - - // mint ASTRO to Auction Contract - mint_some_astro( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - Uint128::new(100_000_000_000), - auction_instance.to_string(), - ); - - let (user1_address, user2_address, user3_address) = make_astro_ust_deposits( - &mut app, - auction_instance.clone(), - auction_init_msg.clone(), - astro_token_instance.clone(), - ); - - // ###### Initialize generator and vesting instance ###### - let (generator_instance, _) = instantiate_generator_and_vesting( - &mut app, - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - astro_token_instance.clone(), - lp_token_instance.clone(), - token_code_id, - pair_code_id, - ); - - let update_msg = UpdateConfigMsg { - owner: None, - astro_ust_pair_address: None, - generator_contract: Some(generator_instance.to_string()), - }; - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Deposit/withdrawal windows are open ###### - - let mut err = app - .execute_contract( - user1_address.clone(), - auction_instance.clone(), - &withdraw_lp_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Astro/USD should be provided to the pool!" - ); - - // finish deposit / withdraw period - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10611001) - }); - - // ###### ERROR :: Invalid request. No LP Tokens to claim ###### - - err = app - .execute_contract( - Addr::unchecked("not_user".to_string()), - auction_instance.clone(), - &withdraw_lp_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "astroport_periphery::auction::UserInfo not found" - ); - - // ###### Sucess :: Initialize ASTRO-UST Pool ###### - - app.execute_contract( - owner.clone(), - astro_token_instance, - &Cw20ExecuteMsg::Send { - amount: Uint128::new(100_000_000000), - contract: auction_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.clone().unwrap()), - auction_instance.clone(), - &ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap(); - - // ###### SUCCESS :: Stake successfully ###### - - app.execute_contract( - Addr::unchecked(auction_init_msg.owner.unwrap()), - auction_instance.clone(), - &ExecuteMsg::StakeLpTokens {}, - &[], - ) - .unwrap(); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10911001) - }); - - // ###### SUCCESS :: Successfully withdraw LP shares (which also claims rewards) for User-1 ###### - - // Auction :: Check user-1 state (before claim) - let user1info_before_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(0u64), - user1info_before_claim.claimed_lp_shares - ); - - // Auction :: Withdraw unvested LP shares for the user - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &ExecuteMsg::ClaimRewards { - withdraw_lp_shares: Some(user1info_before_claim.withdrawable_lp_shares.unwrap()), - }, - &[], - ) - .unwrap(); - - // Auction :: Check user-1 state (After Claim) - let user1info_after_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user1info_before_claim.withdrawable_lp_shares.unwrap(), - user1info_after_claim.claimed_lp_shares - ); - assert_eq!( - Uint128::from(0u64), - user1info_after_claim.withdrawable_lp_shares.unwrap() - ); - - // ###### SUCCESS :: Successfully withdraw LP shares (which also claims rewards) for User-2 ###### - - // Auction :: Check user-2 state (before claim) - let user2info_before_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(0u64), - user2info_before_claim.claimed_lp_shares - ); - - // Auction :: Withdraw unvested LP shares for the user - app.execute_contract( - user2_address.clone(), - auction_instance.clone(), - &ExecuteMsg::ClaimRewards { - withdraw_lp_shares: Some(user2info_before_claim.withdrawable_lp_shares.unwrap()), - }, - &[], - ) - .unwrap(); - - // Auction :: Check user-2 state (After Claim) - let user2info_after_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user2_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user2info_before_claim.withdrawable_lp_shares.unwrap(), - user2info_after_claim.claimed_lp_shares - ); - assert_eq!( - Uint128::from(0u64), - user2info_after_claim.withdrawable_lp_shares.unwrap() - ); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(10991001) - }); - - // ###### SUCCESS :: Successfully withdraw LP shares (which also claims rewards) for User-3 ###### - - // Auction :: Check user-3 state (before claim) - let user3info_before_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user3_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(0u64), - user3info_before_claim.claimed_lp_shares - ); - - // Auction :: Withdraw unvested LP shares for the user - app.execute_contract( - user3_address.clone(), - auction_instance.clone(), - &ExecuteMsg::ClaimRewards { - withdraw_lp_shares: Some(user3info_before_claim.withdrawable_lp_shares.unwrap()), - }, - &[], - ) - .unwrap(); - - // Auction :: Check user-3 state (After Claim) - let user3info_after_claim: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user3_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user3info_before_claim.withdrawable_lp_shares.unwrap(), - user3info_after_claim.claimed_lp_shares - ); - assert_eq!( - Some(Uint128::zero()), - user3info_after_claim.withdrawable_lp_shares - ); - - // ###### SUCCESS :: Successfully again withdraw LP shares (which also claims rewards) for User-1 ###### - - // Auction :: Check user-1 state (before claim) - let user1info_before_claim2: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - - // Auction :: Withdraw LP for the user - app.execute_contract( - user1_address.clone(), - auction_instance.clone(), - &ExecuteMsg::ClaimRewards { - withdraw_lp_shares: Some(user1info_before_claim2.withdrawable_lp_shares.unwrap()), - }, - &[], - ) - .unwrap(); - - // Auction :: Check user-1 state (After Claim) - let user1info_after_claim2: astroport_periphery::auction::UserInfoResponse = app - .wrap() - .query_wasm_smart( - &auction_instance, - &astroport_periphery::auction::QueryMsg::UserInfo { - address: user1_address.to_string(), - }, - ) - .unwrap(); - assert_eq!( - user1info_before_claim2.claimed_lp_shares - + user1info_before_claim2.withdrawable_lp_shares.unwrap(), - user1info_after_claim2.claimed_lp_shares - ); - assert_eq!( - Some(Uint128::zero()), - user1info_after_claim2.withdrawable_lp_shares - ); -} diff --git a/contracts/lockdrop/Cargo.toml b/contracts/lockdrop/Cargo.toml index f070f80d..405201b3 100644 --- a/contracts/lockdrop/Cargo.toml +++ b/contracts/lockdrop/Cargo.toml @@ -54,7 +54,6 @@ astroport-generator-proxy-to-mirror = { git = "https://github.com/astroport-fi/a astroport-staking = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" } astroport-xastro-token = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" } astroport-auction = { path = "../auction" } -astroport-airdrop = { path = "../airdrop" } astroport-whitelist = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" } astroport-governance = { git = "https://github.com/astroport-fi/astroport-governance.git", branch = "main" } voting-escrow = { git = "https://github.com/astroport-fi/astroport-governance.git", branch = "main" } diff --git a/contracts/lockdrop/src/contract.rs b/contracts/lockdrop/src/contract.rs index 90eb937d..2cf12695 100644 --- a/contracts/lockdrop/src/contract.rs +++ b/contracts/lockdrop/src/contract.rs @@ -260,12 +260,11 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S config.owner, OWNERSHIP_PROPOSAL, ) - .map_err(|e| e) } ExecuteMsg::DropOwnershipProposal {} => { let config: Config = CONFIG.load(deps.storage)?; - drop_ownership_proposal(deps, info, config.owner, OWNERSHIP_PROPOSAL).map_err(|e| e) + drop_ownership_proposal(deps, info, config.owner, OWNERSHIP_PROPOSAL) } ExecuteMsg::ClaimOwnership {} => { claim_ownership(deps, info, env, OWNERSHIP_PROPOSAL, |deps, new_owner| { @@ -276,7 +275,6 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S Ok(()) }) - .map_err(|e| e) } } } @@ -2672,7 +2670,7 @@ mod unit_tests { let terraswap_lp_addr = Addr::unchecked("tswp_lp_token"); let migration_info = MigrationInfo { terraswap_migrated_amount: Uint128::from(100_000000u128), - astroport_lp_token: astroport_lp_token.clone(), + astroport_lp_token, }; let pool_info = PoolInfo { terraswap_pool: Addr::unchecked(terraswap_lp_addr.clone()), @@ -2731,7 +2729,7 @@ mod unit_tests { { assert_eq!(contract_addr.to_owned(), "minter_address".to_string()); assert_eq!( - from_binary::(&msg).unwrap(), + from_binary::(msg).unwrap(), astroport::pair_stable_bluna::ExecuteMsg::ClaimReward { receiver: None } ) } else { @@ -2750,7 +2748,7 @@ mod unit_tests { lock_duration: 10, previous_balance: init_uusd_balance, }); - assert_eq!(from_binary::(&msg).unwrap(), real_message); + assert_eq!(from_binary::(msg).unwrap(), real_message); } else { panic!("Wrong message") } @@ -2819,7 +2817,7 @@ mod unit_tests { assert_eq!(res.u128(), 700u128); // emulating newly arrived rewards - total_reward_index = total_reward_index + Decimal256::from_ratio(100u128, 1000u128); + total_reward_index += Decimal256::from_ratio(100u128, 1000u128); let res = calc_user_reward( &deps.storage, @@ -2912,7 +2910,7 @@ mod unit_tests { let terraswap_lp_addr = Addr::unchecked("tswp_lp_token"); let migration_info = MigrationInfo { terraswap_migrated_amount: Uint128::from(100_000000u128), - astroport_lp_token: astroport_lp_token.clone(), + astroport_lp_token, }; let pool_info = PoolInfo { terraswap_pool: Addr::unchecked(terraswap_lp_addr.clone()), @@ -3056,7 +3054,7 @@ mod unit_tests { // the user should receive rewards from the seconds distribution let resp = callback_distribute_asset_reward( deps.as_mut(), - env.clone(), + env, uusd_balance, terraswap_lp_addr.clone(), user_addr.clone(), diff --git a/contracts/lockdrop/src/migration.rs b/contracts/lockdrop/src/migration.rs index 55d8bb82..61d4c914 100644 --- a/contracts/lockdrop/src/migration.rs +++ b/contracts/lockdrop/src/migration.rs @@ -9,7 +9,7 @@ use astroport::restricted_vector::RestrictedVector; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct PoolInfoV101 { pub terraswap_pool: Addr, pub terraswap_amount_in_lockups: Uint128, @@ -26,7 +26,7 @@ pub struct PoolInfoV101 { pub is_staked: bool, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct PoolInfoV111 { pub terraswap_pool: Addr, pub terraswap_amount_in_lockups: Uint128, diff --git a/contracts/lockdrop/src/mock_querier.rs b/contracts/lockdrop/src/mock_querier.rs index e2c35ad7..d199ba08 100644 --- a/contracts/lockdrop/src/mock_querier.rs +++ b/contracts/lockdrop/src/mock_querier.rs @@ -59,7 +59,7 @@ impl WasmMockQuerier { match &request { QueryRequest::Wasm(WasmQuery::Smart { contract_addr, msg }) => { match contract_addr.as_str() { - "factory" => match from_binary(&msg).unwrap() { + "factory" => match from_binary(msg).unwrap() { FeeInfo { .. } => SystemResult::Ok( to_binary(&FeeInfoResponse { fee_address: Some(Addr::unchecked("fee_address")), @@ -81,7 +81,7 @@ impl WasmMockQuerier { ), _ => panic!("DO NOT ENTER HERE"), }, - "minter_address" => match from_binary(&msg).unwrap() { + "minter_address" => match from_binary(msg).unwrap() { Pair {} => SystemResult::Ok( to_binary(&PairInfo { asset_infos: [ @@ -100,7 +100,7 @@ impl WasmMockQuerier { ), _ => panic!("DO NOT ENTER HERE"), }, - _ => match from_binary(&msg).unwrap() { + _ => match from_binary(msg).unwrap() { Cw20QueryMsg::TokenInfo {} => { let balances: &HashMap = match self.token_querier.balances.get(contract_addr) { @@ -121,7 +121,7 @@ impl WasmMockQuerier { name: "mAPPL".to_string(), symbol: "mAPPL".to_string(), decimals: 6, - total_supply: total_supply, + total_supply, }) .into(), ) diff --git a/contracts/lockdrop/src/testing.rs b/contracts/lockdrop/src/testing.rs index ef10f906..92f9156f 100644 --- a/contracts/lockdrop/src/testing.rs +++ b/contracts/lockdrop/src/testing.rs @@ -81,6 +81,6 @@ fn update_owner() { // Let's query the state let config: Config = - from_binary(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()).unwrap(); + from_binary(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(); assert_eq!(new_owner, config.owner); } diff --git a/contracts/lockdrop/tests/integration.rs b/contracts/lockdrop/tests/integration.rs deleted file mode 100644 index 22b2ecca..00000000 --- a/contracts/lockdrop/tests/integration.rs +++ /dev/null @@ -1,3952 +0,0 @@ -use astroport::asset::AssetInfo; -use astroport::restricted_vector::RestrictedVector; -use astroport_governance::utils::EPOCH_START; -use astroport_periphery::{ - auction::{ExecuteMsg as AuctionExecuteMsg, UpdateConfigMsg as AuctionUpdateConfigMsg}, - lockdrop::{ - self, Cw20HookMsg, ExecuteMsg, InstantiateMsg, MigrationInfo, QueryMsg, StateResponse, - UpdateConfigMsg, UserInfoResponse, - }, -}; -use cosmwasm_std::testing::{mock_env, MockApi, MockStorage}; -use cosmwasm_std::{ - attr, to_binary, Addr, Coin, Decimal, Timestamp, Uint128, Uint256 as CUint256, Uint64, -}; - -use astroport::token::InstantiateMsg as TokenInstantiateMsg; -use astroport_periphery::lockdrop::{Config, PoolInfo}; -use cw20::{Cw20ExecuteMsg, Cw20QueryMsg}; -use cw_multi_test::{App, AppBuilder, BankKeeper, ContractWrapper, Executor}; - -fn mock_app() -> App { - let mut env = mock_env(); - env.block.time = Timestamp::from_seconds(EPOCH_START); - let api = MockApi::default(); - let bank = BankKeeper::new(); - let storage = MockStorage::new(); - - AppBuilder::new() - .with_api(api) - .with_block(env.block) - .with_bank(bank) - .with_storage(storage) - .build(|_, _, _| {}) -} - -// Instantiate ASTRO Token Contract -fn instantiate_astro_token(app: &mut App, owner: Addr) -> Addr { - let astro_token_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let astro_token_code_id = app.store_code(astro_token_contract); - - let msg = TokenInstantiateMsg { - name: String::from("Astro token"), - symbol: String::from("ASTRO"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }; - - let astro_token_instance = app - .instantiate_contract( - astro_token_code_id, - owner.clone(), - &msg, - &[], - String::from("ASTRO"), - None, - ) - .unwrap(); - astro_token_instance -} - -// Instantiate Terraswap -fn instantiate_terraswap(app: &mut App, owner: Addr) -> Addr { - // Terraswap Pair - let terraswap_pair_contract = Box::new(ContractWrapper::new_with_empty( - terraswap_pair::contract::execute, - terraswap_pair::contract::instantiate, - terraswap_pair::contract::query, - )); - let terraswap_pair_code_id = app.store_code(terraswap_pair_contract); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - // Terraswap Factory Contract - let terraswap_factory_contract = Box::new(ContractWrapper::new_with_empty( - terraswap_factory::contract::execute, - terraswap_factory::contract::instantiate, - terraswap_factory::contract::query, - )); - - let terraswap_factory_code_id = app.store_code(terraswap_factory_contract); - - let msg = terraswap::factory::InstantiateMsg { - pair_code_id: terraswap_pair_code_id, - token_code_id: terraswap_token_code_id, - }; - - let terraswap_factory_instance = app - .instantiate_contract( - terraswap_factory_code_id, - owner.clone(), - &msg, - &[], - String::from("Terraswap_Factory"), - None, - ) - .unwrap(); - terraswap_factory_instance -} - -// Instantiate Astroport -fn instantiate_astroport(app: &mut App, owner: Addr) -> Addr { - let mut pair_configs = vec![]; - // Astroport Pair - let astroport_pair_contract = Box::new( - ContractWrapper::new_with_empty( - astroport_pair::contract::execute, - astroport_pair::contract::instantiate, - astroport_pair::contract::query, - ) - .with_reply_empty(astroport_pair::contract::reply), - ); - let astroport_pair_code_id = app.store_code(astroport_pair_contract); - pair_configs.push(astroport::factory::PairConfig { - code_id: astroport_pair_code_id, - pair_type: astroport::factory::PairType::Xyk {}, - total_fee_bps: 5u16, - maker_fee_bps: 3u16, - is_disabled: false, - is_generator_disabled: false, - }); - - // Astroport Pair :: Stable - let astroport_pair_stable_contract = Box::new( - ContractWrapper::new_with_empty( - astroport_pair_stable::contract::execute, - astroport_pair_stable::contract::instantiate, - astroport_pair_stable::contract::query, - ) - .with_reply_empty(astroport_pair_stable::contract::reply), - ); - let astroport_pair_stable_code_id = app.store_code(astroport_pair_stable_contract); - pair_configs.push(astroport::factory::PairConfig { - code_id: astroport_pair_stable_code_id, - pair_type: astroport::factory::PairType::Stable {}, - total_fee_bps: 5u16, - maker_fee_bps: 3u16, - is_disabled: false, - is_generator_disabled: false, - }); - - // Astroport LP Token - let astroport_token_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - let astroport_token_code_id = app.store_code(astroport_token_contract); - - // Astroport Factory Contract - let astroport_factory_contract = Box::new( - ContractWrapper::new_with_empty( - astroport_factory::contract::execute, - astroport_factory::contract::instantiate, - astroport_factory::contract::query, - ) - .with_reply_empty(astroport_factory::contract::reply), - ); - - let astroport_factory_code_id = app.store_code(astroport_factory_contract); - - let whitelist_contract = Box::new(ContractWrapper::new_with_empty( - astroport_whitelist::contract::execute, - astroport_whitelist::contract::instantiate, - astroport_whitelist::contract::query, - )); - - let whitelist_code_id = app.store_code(whitelist_contract); - - let msg = astroport::factory::InstantiateMsg { - /// Pair contract code IDs which are allowed to create pairs - pair_configs, - token_code_id: astroport_token_code_id, - fee_address: Some("fee_address".to_string()), - generator_address: Some("generator_address".to_string()), - owner: owner.clone().to_string(), - whitelist_code_id, - }; - - let astroport_factory_instance = app - .instantiate_contract( - astroport_factory_code_id, - owner.clone(), - &msg, - &[], - String::from("Astroport_Factory"), - None, - ) - .unwrap(); - astroport_factory_instance -} - -// Instantiate Astroport's generator and vesting contracts -fn instantiate_generator_and_vesting( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, - astro_factory_instance: Addr, -) -> (Addr, Addr) { - // Vesting - let vesting_contract = Box::new(ContractWrapper::new_with_empty( - astroport_vesting::contract::execute, - astroport_vesting::contract::instantiate, - astroport_vesting::contract::query, - )); - let vesting_code_id = app.store_code(vesting_contract); - - let init_msg = astroport::vesting::InstantiateMsg { - owner: owner.to_string(), - token_addr: astro_token_instance.clone().to_string(), - }; - - let vesting_instance = app - .instantiate_contract( - vesting_code_id, - owner.clone(), - &init_msg, - &[], - "Vesting", - None, - ) - .unwrap(); - - mint_some_tokens( - app, - owner.clone(), - astro_token_instance.clone(), - Uint128::new(900_000_000_000), - owner.to_string(), - ); - app.execute_contract( - owner.clone(), - astro_token_instance.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: vesting_instance.clone().to_string(), - amount: Uint128::new(900_000_000_000), - expires: None, - }, - &[], - ) - .unwrap(); - - let whitelist_contract = Box::new(ContractWrapper::new_with_empty( - astroport_whitelist::contract::execute, - astroport_whitelist::contract::instantiate, - astroport_whitelist::contract::query, - )); - - let whitelist_code_id = app.store_code(whitelist_contract); - - // Generator - let generator_contract = Box::new( - ContractWrapper::new_with_empty( - astroport_generator::contract::execute, - astroport_generator::contract::instantiate, - astroport_generator::contract::query, - ) - .with_reply_empty(astroport_generator::contract::reply), - ); - - let generator_code_id = app.store_code(generator_contract); - - let init_msg = astroport::generator::InstantiateMsg { - allowed_reward_proxies: vec![], - start_block: Uint64::from(app.block_info().height), - astro_token: astro_token_instance.to_string(), - tokens_per_block: Uint128::from(0u128), - vesting_contract: vesting_instance.clone().to_string(), - owner: owner.to_string(), - factory: astro_factory_instance.to_string(), - generator_controller: None, - voting_escrow: None, - guardian: None, - whitelist_code_id, - }; - - let generator_instance = app - .instantiate_contract( - generator_code_id, - owner.clone(), - &init_msg, - &[], - "Generator", - None, - ) - .unwrap(); - - let tokens_per_block = Uint128::new(10_000000); - - let msg = astroport::generator::ExecuteMsg::SetTokensPerBlock { - amount: tokens_per_block, - }; - app.execute_contract(owner.clone(), generator_instance.clone(), &msg, &[]) - .unwrap(); - - let msg = astroport::generator::QueryMsg::Config {}; - let res: astroport::generator::Config = app - .wrap() - .query_wasm_smart(&generator_instance, &msg) - .unwrap(); - assert_eq!(res.tokens_per_block, tokens_per_block); - - // vesting to generator: - - let current_block = app.block_info(); - - let amount = Uint128::new(630720000000); - - let msg = Cw20ExecuteMsg::Send { - contract: vesting_instance.to_string(), - amount, - msg: to_binary(&astroport::vesting::Cw20HookMsg::RegisterVestingAccounts { - vesting_accounts: vec![astroport::vesting::VestingAccount { - address: generator_instance.to_string(), - schedules: vec![astroport::vesting::VestingSchedule { - start_point: astroport::vesting::VestingSchedulePoint { - time: current_block.time.seconds(), - amount, - }, - end_point: None, - }], - }], - }) - .unwrap(), - }; - - app.execute_contract(owner.clone(), astro_token_instance.clone(), &msg, &[]) - .unwrap(); - - (generator_instance, vesting_instance) -} - -// Mints some Tokens to "to" recipient -fn mint_some_tokens(app: &mut App, owner: Addr, token_instance: Addr, amount: Uint128, to: String) { - let msg = cw20::Cw20ExecuteMsg::Mint { - recipient: to.clone(), - amount: amount, - }; - let res = app - .execute_contract(owner.clone(), token_instance.clone(), &msg, &[]) - .unwrap(); - assert_eq!(res.events[1].attributes[1], attr("action", "mint")); - assert_eq!(res.events[1].attributes[2], attr("to", to)); - assert_eq!(res.events[1].attributes[3], attr("amount", amount)); -} - -// Instantiate AUCTION Contract -fn instantiate_auction_contract( - app: &mut App, - owner: Addr, - astro_token_instance: Addr, - airdrop_instance: Addr, - lockdrop_instance: Addr, - pair_instance: Addr, - generator_instance: Addr, -) -> (Addr, astroport_periphery::auction::InstantiateMsg) { - let auction_contract = Box::new(ContractWrapper::new_with_empty( - astroport_auction::contract::execute, - astroport_auction::contract::instantiate, - astroport_auction::contract::query, - )); - - let auction_code_id = app.store_code(auction_contract); - - let auction_instantiate_msg = astroport_periphery::auction::InstantiateMsg { - owner: Some(owner.to_string()), - astro_token_address: astro_token_instance.clone().into_string(), - airdrop_contract_address: airdrop_instance.to_string(), - lockdrop_contract_address: lockdrop_instance.to_string(), - lp_tokens_vesting_duration: 7776000u64, - init_timestamp: EPOCH_START + 10_600_000, - deposit_window: 100_00_0, - withdrawal_window: 5_00_00, - }; - - // Init contract - let auction_instance = app - .instantiate_contract( - auction_code_id, - owner.clone(), - &auction_instantiate_msg, - &[], - "auction", - None, - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - auction_instance.clone(), - &AuctionExecuteMsg::UpdateConfig { - new_config: AuctionUpdateConfigMsg { - astro_ust_pair_address: Some(pair_instance.to_string()), - owner: None, - generator_contract: Some(generator_instance.to_string()), - }, - }, - &[], - ) - .unwrap(); - (auction_instance, auction_instantiate_msg) -} - -// Instantiate LOCKDROP Contract -fn instantiate_lockdrop_contract(app: &mut App, owner: Addr) -> (Addr, InstantiateMsg) { - let lockdrop_contract = Box::new(ContractWrapper::new_with_empty( - astroport_lockdrop::contract::execute, - astroport_lockdrop::contract::instantiate, - astroport_lockdrop::contract::query, - )); - - let lockdrop_code_id = app.store_code(lockdrop_contract); - - let lockdrop_instantiate_msg = InstantiateMsg { - owner: Some(owner.clone().to_string()), - init_timestamp: EPOCH_START + 100_000, - deposit_window: 10_000_000, - withdrawal_window: 500_000, - min_lock_duration: 1u64, - max_lock_duration: 52u64, - weekly_multiplier: 1u64, - weekly_divider: 12u64, - max_positions_per_user: 14, - }; - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 900_00) - }); - - // Init contract - let lockdrop_instance = app - .instantiate_contract( - lockdrop_code_id, - owner.clone(), - &lockdrop_instantiate_msg, - &[], - "lockdrop", - None, - ) - .unwrap(); - (lockdrop_instance, lockdrop_instantiate_msg) -} - -// Instantiate -fn instantiate_all_contracts( - app: &mut App, - owner: Addr, -) -> (Addr, Addr, Addr, Addr, UpdateConfigMsg) { - let (lockdrop_instance, _lockdrop_instantiate_msg) = - instantiate_lockdrop_contract(app, owner.clone()); - - let astro_token = instantiate_astro_token(app, owner.clone()); - - // Initiate Terraswap - let terraswap_factory_instance = instantiate_terraswap(app, owner.clone()); - - // Initiate ASTRO-UST Pair on Astroport - let astroport_factory_instance = instantiate_astroport(app, owner.clone()); - let pair_info = [ - astroport::asset::AssetInfo::Token { - contract_addr: astro_token.clone(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ]; - app.execute_contract( - Addr::unchecked("user"), - astroport_factory_instance.clone(), - &astroport::factory::ExecuteMsg::CreatePair { - asset_infos: pair_info.clone(), - init_params: None, - pair_type: astroport::factory::PairType::Xyk {}, - }, - &[], - ) - .unwrap(); - let pair_resp: astroport::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &astroport_factory_instance, - &astroport::factory::QueryMsg::Pair { - asset_infos: pair_info.clone(), - }, - ) - .unwrap(); - let pool_address = pair_resp.contract_addr; - - let (generator_address, _) = instantiate_generator_and_vesting( - app, - owner.clone(), - astro_token.clone(), - astroport_factory_instance.clone(), - ); - - // Airdrop Contract - let airdrop_contract = Box::new(ContractWrapper::new_with_empty( - astroport_airdrop::contract::execute, - astroport_airdrop::contract::instantiate, - astroport_airdrop::contract::query, - )); - - let airdrop_code_id = app.store_code(airdrop_contract); - - let airdrop_msg = astroport_periphery::airdrop::InstantiateMsg { - owner: Some(owner.clone().to_string()), - astro_token_address: astro_token.clone().into_string(), - merkle_roots: Some(vec!["merkle_roots".to_string()]), - from_timestamp: Some(1_000_00), - to_timestamp: 10000_000_00, - }; - - let airdrop_instance = app - .instantiate_contract( - airdrop_code_id, - owner.clone(), - &airdrop_msg, - &[], - String::from("airdrop_instance"), - None, - ) - .unwrap(); - - // Initiate Auction contract - let (auction_contract, _) = instantiate_auction_contract( - app, - owner.clone(), - astro_token.clone(), - airdrop_instance.clone(), - lockdrop_instance.clone(), - pool_address, - generator_address.clone(), - ); - - // Set auction contract in airdrop contract - app.execute_contract( - owner.clone(), - airdrop_instance.clone(), - &astroport_periphery::airdrop::ExecuteMsg::UpdateConfig { - owner: None, - auction_contract_address: Some(auction_contract.clone().to_string()), - merkle_roots: None, - from_timestamp: None, - to_timestamp: None, - }, - &[], - ) - .unwrap(); - - let update_msg = UpdateConfigMsg { - astro_token_address: Some(astro_token.to_string()), - auction_contract_address: Some(auction_contract.to_string()), - generator_address: Some(generator_address.to_string()), - }; - app.execute_contract( - owner.clone(), - astro_token.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: lockdrop_instance.clone().to_string(), - amount: Uint128::new(1000000000u128), - expires: None, - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - astro_token.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(1000000000u64), - contract: lockdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - return ( - astro_token, - lockdrop_instance, - astroport_factory_instance, - terraswap_factory_instance, - update_msg, - ); -} - -// Instantiate Pools and Migrate Liquidity to Astroport -fn initialize_and_migrate_liquidity_for_pool( - app: &mut App, - owner: Addr, - token_instance: Addr, - lockdrop_instance: Addr, - astroport_factory_instance: Addr, -) -> (String, Addr, Addr) { - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - // Terraswap Pair - let terraswap_pair_contract = Box::new( - ContractWrapper::new_with_empty( - terraswap_pair::contract::execute, - terraswap_pair::contract::instantiate, - terraswap_pair::contract::query, - ) - .with_reply_empty(terraswap_pair::contract::reply), - ); - let terraswap_pair_code_id = app.store_code(terraswap_pair_contract); - - // LP POOL INSTANCE - let terraswap_pool_instance = app - .instantiate_contract( - terraswap_pair_code_id, - Addr::unchecked("user".to_string()), - &terraswap::pair::InstantiateMsg { - asset_infos: [ - terraswap::asset::AssetInfo::Token { - contract_addr: token_instance.clone().to_string(), - }, - terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - token_code_id: terraswap_token_code_id, - asset_decimals: [6, 6], - }, - &[], - String::from("terraswap_pool"), - None, - ) - .unwrap(); - - // Query LP Token - let pair_response: terraswap::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &terraswap_pool_instance, - &terraswap::pair::QueryMsg::Pair {}, - ) - .unwrap(); - let terraswap_token_instance = pair_response.liquidity_token; - - // SUCCESSFULLY INITIALIZES POOL - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Mint ANC to users - app.execute_contract( - owner.clone(), - token_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user_address.clone(), - amount: Uint128::from(10000_000000u64), - }, - &[], - ) - .unwrap(); - app.execute_contract( - owner.clone(), - token_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user2_address.clone(), - amount: Uint128::from(10000_000000u64), - }, - &[], - ) - .unwrap(); - - // Set UST user balances - app.init_modules(|router, _, storage| { - router - .bank - .init_balance( - storage, - &Addr::unchecked(user_address.clone()), - vec![Coin::new(1000000_000000, "uusd")], - ) - .unwrap(); - router - .bank - .init_balance( - storage, - &Addr::unchecked(user2_address.clone()), - vec![Coin::new(1000000_000000, "uusd")], - ) - .unwrap(); - }); - - // user#1 adds liquidity to Terraswap Pool and locks that in Lockdrop contract - // increase allowance - app.execute_contract( - Addr::unchecked(user_address.clone()), - token_instance.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: terraswap_pool_instance.clone().to_string(), - amount: Uint128::new(1000_000000), - expires: None, - }, - &[], - ) - .unwrap(); - - // add Liquidity to Terraswap pool - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_pool_instance.clone(), - &terraswap::pair::ExecuteMsg::ProvideLiquidity { - assets: [ - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::Token { - contract_addr: token_instance.clone().to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - ], - slippage_tolerance: None, - receiver: None, - }, - &[Coin::new(1000_000000, "uusd")], - ) - .unwrap(); - - // Query LP balance - let lp_balance_res: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &terraswap_token_instance.clone(), - &cw20::Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - let user_lp_balance = lp_balance_res.balance; - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 1_000_00) - }); - - // Lock LP Tokens into Lockup Position - app.execute_contract( - Addr::unchecked(user_address.clone()), - Addr::unchecked(terraswap_token_instance.clone()), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: user_lp_balance, - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // user#2 adds liquidity to Terraswap Pool and locks that in Lockdrop contract - // increase allowance - app.execute_contract( - Addr::unchecked(user2_address.clone()), - token_instance.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: terraswap_pool_instance.clone().to_string(), - amount: Uint128::new(1000_000000), - expires: None, - }, - &[], - ) - .unwrap(); - - // add Liquidity to Terraswap pool - app.execute_contract( - Addr::unchecked(user2_address.clone()), - terraswap_pool_instance.clone(), - &terraswap::pair::ExecuteMsg::ProvideLiquidity { - assets: [ - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::Token { - contract_addr: token_instance.clone().to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - ], - slippage_tolerance: None, - receiver: None, - }, - &[Coin::new(1000_000000, "uusd")], - ) - .unwrap(); - - // Query LP balance - let lp_balance_res: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &terraswap_token_instance.clone(), - &cw20::Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - let user_lp_balance = lp_balance_res.balance; - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 1_000_00) - }); - - // Lock LP Tokens into Lockup Position - app.execute_contract( - Addr::unchecked(user2_address.clone()), - Addr::unchecked(terraswap_token_instance.clone()), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: user_lp_balance, - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // Increase timestamp for window closure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // Create Astroport Pair - app.execute_contract( - Addr::unchecked("user"), - astroport_factory_instance.clone(), - &astroport::factory::ExecuteMsg::CreatePair { - asset_infos: [ - astroport::asset::AssetInfo::Token { - contract_addr: token_instance.clone(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - init_params: None, - pair_type: astroport::factory::PairType::Xyk {}, - }, - &[], - ) - .unwrap(); - - // Query Astroport addresses - let pair_resp: astroport::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &astroport_factory_instance, - &astroport::factory::QueryMsg::Pair { - asset_infos: [ - astroport::asset::AssetInfo::Token { - contract_addr: token_instance.clone(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - }, - ) - .unwrap(); - let astro_pool_address = pair_resp.contract_addr; - let astro_lp_address = pair_resp.liquidity_token; - - // Migrate Liquidity - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &ExecuteMsg::MigrateLiquidity { - terraswap_lp_token: terraswap_token_instance.clone(), - astroport_pool_addr: astro_pool_address.to_string(), - slippage_tolerance: None, - }, - &[], - ) - .unwrap(); - - return ( - terraswap_token_instance, - astro_lp_address, - astro_pool_address, - ); -} - -#[test] -fn proper_initialization_lockdrop() { - let owner = Addr::unchecked("contract_owner"); - let mut app = mock_app(); - - let (lockdrop_instance, lockdrop_instantiate_msg) = - instantiate_lockdrop_contract(&mut app, owner); - - let resp: Config = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - // Check config - assert_eq!( - lockdrop_instantiate_msg.owner.unwrap().to_string(), - resp.owner - ); - assert_eq!(None, resp.astro_token); - assert_eq!(None, resp.auction_contract); - assert_eq!(None, resp.generator); - assert_eq!(lockdrop_instantiate_msg.init_timestamp, resp.init_timestamp); - assert_eq!(lockdrop_instantiate_msg.deposit_window, resp.deposit_window); - assert_eq!( - lockdrop_instantiate_msg.withdrawal_window, - resp.withdrawal_window - ); - assert_eq!( - lockdrop_instantiate_msg.min_lock_duration, - resp.min_lock_duration - ); - assert_eq!( - lockdrop_instantiate_msg.max_lock_duration, - resp.max_lock_duration - ); - assert_eq!( - lockdrop_instantiate_msg.weekly_multiplier, - resp.weekly_multiplier - ); - assert_eq!(lockdrop_instantiate_msg.weekly_divider, resp.weekly_divider); - assert_eq!(Uint128::zero(), resp.lockdrop_incentives); - - // Check state - let resp: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - - assert_eq!(0u64, resp.total_incentives_share); - assert_eq!(Uint128::zero(), resp.total_astro_delegated); - assert_eq!(false, resp.are_claims_allowed); -} - -#[test] -fn test_update_config() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (lockdrop_instance, _lockdrop_instantiate_msg) = - instantiate_lockdrop_contract(&mut app, owner.clone()); - - let astro_token = instantiate_astro_token(&mut app, owner.clone()); - - // Initiate ASTRO-UST Pair on Astroport - let astroport_factory_instance = instantiate_astroport(&mut app, owner.clone()); - let pair_info = [ - astroport::asset::AssetInfo::Token { - contract_addr: astro_token.clone(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ]; - app.execute_contract( - Addr::unchecked("user"), - astroport_factory_instance.clone(), - &astroport::factory::ExecuteMsg::CreatePair { - asset_infos: pair_info.clone(), - init_params: None, - pair_type: astroport::factory::PairType::Xyk {}, - }, - &[], - ) - .unwrap(); - let pair_resp: astroport::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &astroport_factory_instance, - &astroport::factory::QueryMsg::Pair { - asset_infos: pair_info.clone(), - }, - ) - .unwrap(); - let pool_address = pair_resp.contract_addr; - - let (generator_address, _) = instantiate_generator_and_vesting( - &mut app, - owner.clone(), - astro_token.clone(), - astroport_factory_instance.clone(), - ); - - // Initiate Auction contract - let (auction_contract, _) = instantiate_auction_contract( - &mut app, - owner.clone(), - astro_token.clone(), - Addr::unchecked("auction_instance"), - lockdrop_instance.clone(), - pool_address, - generator_address.clone(), - ); - - let update_msg = UpdateConfigMsg { - astro_token_address: Some(astro_token.to_string()), - auction_contract_address: Some(auction_contract.to_string()), - generator_address: Some(generator_address.to_string()), - }; - - // ###### ERROR :: Unauthorized ###### - let err = app - .execute_contract( - Addr::unchecked("wrong_owner"), - lockdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### SUCCESS :: Should have successfully updated ###### - - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - astro_token.clone(), - &Cw20ExecuteMsg::Send { - amount: Uint128::from(1000000000u64), - contract: lockdrop_instance.to_string(), - msg: to_binary(&Cw20HookMsg::IncreaseAstroIncentives {}).unwrap(), - }, - &[], - ) - .unwrap(); - - let resp: Config = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::Config {}) - .unwrap(); - - assert_eq!( - update_msg.clone().astro_token_address.unwrap(), - resp.astro_token.unwrap() - ); - assert_eq!( - update_msg.clone().auction_contract_address.unwrap(), - resp.auction_contract.unwrap() - ); - assert_eq!( - update_msg.clone().generator_address.unwrap(), - resp.generator.unwrap() - ); - assert_eq!(Uint128::from(1000000000u64), resp.lockdrop_incentives); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // ###### ERROR :: ASTRO tokens are live. Configuration cannot be updated now ###### - app.execute_contract( - Addr::unchecked(auction_contract), - lockdrop_instance.clone(), - &ExecuteMsg::EnableClaims {}, - &[], - ) - .unwrap(); - - let err = app - .execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &ExecuteMsg::UpdateConfig { - new_config: update_msg.clone(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: ASTRO token already set" - ); -} - -#[test] -fn test_initialize_pool() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, _, _, _update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - let terraswap_token_instance = app - .instantiate_contract( - terraswap_token_code_id, - Addr::unchecked("user".to_string()), - &terraswap::token::InstantiateMsg { - name: "terraswap liquidity token".to_string(), - symbol: "uLP".to_string(), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: "pair_instance".to_string(), - cap: None, - }), - }, - &[], - String::from("terraswap_lp_token"), - None, - ) - .unwrap(); - - let initialize_pool_msg = astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }; - - // ###### ERROR :: Unauthorized ###### - let err = app - .execute_contract( - Addr::unchecked("wrong_owner"), - lockdrop_instance.clone(), - &initialize_pool_msg, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY INITIALIZE ###### - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &initialize_pool_msg, - &[], - ) - .unwrap(); - // check state - let state_resp: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(10000000u64, state_resp.total_incentives_share); - assert_eq!(Uint128::zero(), state_resp.total_astro_delegated); - assert_eq!(false, state_resp.are_claims_allowed); - assert_eq!( - vec![terraswap_token_instance.clone()], - state_resp.supported_pairs_list - ); - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!("pair_instance".to_string(), pool_resp.terraswap_pool); - assert_eq!(Uint128::zero(), pool_resp.terraswap_amount_in_lockups); - assert_eq!(None, pool_resp.migration_info); - assert_eq!(10000000u64, pool_resp.incentives_share); - assert_eq!(CUint256::zero(), pool_resp.weighted_amount); - // assert_eq!(Decimal::zero(), pool_resp.generator_astro_per_share); - // assert_eq!(Decimal::zero(), pool_resp.generator_proxy_per_share); - assert_eq!(false, pool_resp.is_staked); - - // ###### ERROR :: Already supported ###### - let err = app - .execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &initialize_pool_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Already supported" - ); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY INITIALIZE #2 ###### - - let terraswap_token_instance2 = app - .instantiate_contract( - terraswap_token_code_id, - Addr::unchecked("user".to_string()), - &terraswap::token::InstantiateMsg { - name: "terraswap liquidity token #2".to_string(), - symbol: "uLP".to_string(), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: "pair_instance#2".to_string(), - cap: None, - }), - }, - &[], - String::from("terraswap_lp_token#2"), - None, - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance2.to_string(), - incentives_share: 10400000u64, - }, - &[], - ) - .unwrap(); - // check state - let state_resp: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(20400000u64, state_resp.total_incentives_share); - assert_eq!( - vec![ - terraswap_token_instance.clone(), - terraswap_token_instance2.clone(), - ], - state_resp.supported_pairs_list - ); - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance2.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!("pair_instance#2".to_string(), pool_resp.terraswap_pool); - assert_eq!(Uint128::zero(), pool_resp.terraswap_amount_in_lockups); - assert_eq!(None, pool_resp.migration_info); - assert_eq!(10400000u64, pool_resp.incentives_share); - - // ###### ERROR :: Pools cannot be added post deposit window closure ###### - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 900000_00) - }); - let err = app - .execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &initialize_pool_msg, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Pools cannot be added post deposit window closure" - ); -} - -#[test] -fn test_update_pool() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, _, _, _update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - let terraswap_token_instance = app - .instantiate_contract( - terraswap_token_code_id, - Addr::unchecked("user".to_string()), - &terraswap::token::InstantiateMsg { - name: "terraswap liquidity token".to_string(), - symbol: "uLP".to_string(), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: "pair_instance".to_string(), - cap: None, - }), - }, - &[], - String::from("terraswap_lp_token"), - None, - ) - .unwrap(); - - // SUCCESSFULLY INITIALIZES POOL - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Unauthorized ###### - let err = app - .execute_contract( - Addr::unchecked("wrong_owner"), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::UpdatePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 3434543u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY UPDATE POOL ###### - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::UpdatePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 3434543u64, - }, - &[], - ) - .unwrap(); - // check state - let state_resp: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(3434543u64, state_resp.total_incentives_share); - assert_eq!(Uint128::zero(), state_resp.total_astro_delegated); - assert_eq!(false, state_resp.are_claims_allowed); - assert_eq!( - vec![terraswap_token_instance.clone()], - state_resp.supported_pairs_list - ); - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!("pair_instance".to_string(), pool_resp.terraswap_pool); - assert_eq!(Uint128::zero(), pool_resp.terraswap_amount_in_lockups); - assert_eq!(None, pool_resp.migration_info); - assert_eq!(3434543u64, pool_resp.incentives_share); - assert_eq!(CUint256::zero(), pool_resp.weighted_amount); - assert_eq!( - Decimal::from_ratio(0u64, 1u64), - pool_resp.generator_astro_per_share - ); - assert_eq!( - RestrictedVector::default(), - pool_resp.generator_proxy_per_share - ); - assert_eq!(false, pool_resp.is_staked); - - // ###### ERROR :: Pools cannot be added post deposit window closure ###### - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 900000_00) - }); - let err = app - .execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::UpdatePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 3434543u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Pools cannot be updated post deposit window closure" - ); -} - -#[test] -fn test_increase_lockup() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, _, _, _) = instantiate_all_contracts(&mut app, owner.clone()); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - // LP Token #1 - let terraswap_token_instance = app - .instantiate_contract( - terraswap_token_code_id, - Addr::unchecked("user".to_string()), - &terraswap::token::InstantiateMsg { - name: "terraswap liquidity token".to_string(), - symbol: "uLP".to_string(), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: "pair_instance".to_string(), - cap: None, - }), - }, - &[], - String::from("terraswap_lp_token"), - None, - ) - .unwrap(); - - // LP Token #2 - let terraswap_token_instance2 = app - .instantiate_contract( - terraswap_token_code_id, - Addr::unchecked("user".to_string()), - &terraswap::token::InstantiateMsg { - name: "terraswap liquidity token".to_string(), - symbol: "uLP".to_string(), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: "pair2_instance".to_string(), - cap: None, - }), - }, - &[], - String::from("terraswap_lp_token2"), - None, - ) - .unwrap(); - - // SUCCESSFULLY INITIALIZES POOL - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Mint some LP tokens to user#1 - app.execute_contract( - Addr::unchecked("pair_instance".to_string()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user_address.clone(), - amount: Uint128::from(124231343u128), - }, - &[], - ) - .unwrap(); - app.execute_contract( - Addr::unchecked("pair2_instance".to_string()), - terraswap_token_instance2.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user_address.clone(), - amount: Uint128::from(100000000u128), - }, - &[], - ) - .unwrap(); - - // Mint some LP tokens to user#2 - app.execute_contract( - Addr::unchecked("pair_instance".to_string()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user2_address.clone(), - amount: Uint128::from(124231343u128), - }, - &[], - ) - .unwrap(); - app.execute_contract( - Addr::unchecked("pair2_instance".to_string()), - terraswap_token_instance2.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user2_address.clone(), - amount: Uint128::from(100000000u128), - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: LP Pool not supported ###### - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance2.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 4u64 }).unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "astroport_periphery::lockdrop::PoolInfo not found" - ); - - // ###### ERROR :: Deposit window closed (havent opened) ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 5u64 }).unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); - - // ###### ERROR :: Lockup duration needs to be between 1 and 52 ###### - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 1_000_00) - }); - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 0u64 }).unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Lockup duration needs to be between 1 and 52" - ); - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 53u64 }).unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Lockup duration needs to be between 1 and 52" - ); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY DEPOSIT LP TOKENS INTO POOL ###### - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 5u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(10000u128), - pool_resp.terraswap_amount_in_lockups - ); - assert_eq!(CUint256::from(13333u64), pool_resp.weighted_amount); - assert_eq!(10000000u64, pool_resp.incentives_share); - - // check User Info - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(1000000000u64), user_resp.total_astro_rewards); - assert_eq!(Uint128::zero(), user_resp.delegated_astro_rewards); - assert_eq!(false, user_resp.astro_transferred); - - assert_eq!( - Uint128::from(10000u128), - user_resp.lockup_infos[0].lp_units_locked - ); - assert_eq!(false, user_resp.lockup_infos[0].withdrawal_flag); - assert_eq!( - user_resp.total_astro_rewards, - user_resp.lockup_infos[0].astro_rewards - ); - assert_eq!(5u64, user_resp.lockup_infos[0].duration); - assert_eq!( - Uint128::zero(), - user_resp.lockup_infos[0].generator_astro_debt - ); - assert_eq!( - RestrictedVector::::default(), - user_resp.lockup_infos[0].generator_proxy_debt - ); - assert_eq!( - EPOCH_START + 13624000u64, - user_resp.lockup_infos[0].unlock_timestamp - ); - assert_eq!(None, user_resp.lockup_infos[0].astroport_lp_units); - assert_eq!(None, user_resp.lockup_infos[0].astroport_lp_token); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY DEPOSIT LP TOKENS INTO POOL (2nd USER) ###### - app.execute_contract( - Addr::unchecked(user2_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(20000u128), - pool_resp.terraswap_amount_in_lockups - ); - assert_eq!(CUint256::from(30833u64), pool_resp.weighted_amount); - - // check User Info - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user2_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(567573703u64), user_resp.total_astro_rewards); - assert_eq!( - Uint128::from(10000u128), - user_resp.lockup_infos[0].lp_units_locked - ); - assert_eq!( - user_resp.total_astro_rewards, - user_resp.lockup_infos[0].astro_rewards - ); - assert_eq!( - EPOCH_START + 16648000u64, - user_resp.lockup_infos[0].unlock_timestamp - ); - - // check User#1 Info (ASTRO rewards should be the latest one) - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(432426296u128), user_resp.total_astro_rewards); - assert_eq!( - Uint128::from(10000u128), - user_resp.lockup_infos[0].lp_units_locked - ); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY AGAIN DEPOSIT LP TOKENS INTO POOL ###### - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 51u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(20010u128), - pool_resp.terraswap_amount_in_lockups - ); - - // check User Info - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(10u128), - user_resp.lockup_infos[1].lp_units_locked - ); - assert_eq!(51u64, user_resp.lockup_infos[1].duration); - assert_eq!(Uint128::from(433363553u128), user_resp.total_astro_rewards); - - // ###### ERROR :: Deposit window closed ###### - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 900_000000) - }); - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(100u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 5u64 }).unwrap(), - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Deposit window closed" - ); -} - -#[test] -fn test_withdraw_from_lockup() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, _, _, _update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - // LP Token #1 - let terraswap_token_instance = app - .instantiate_contract( - terraswap_token_code_id, - Addr::unchecked("user".to_string()), - &terraswap::token::InstantiateMsg { - name: "terraswap liquidity token".to_string(), - symbol: "uLP".to_string(), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: "pair_instance".to_string(), - cap: None, - }), - }, - &[], - String::from("terraswap_lp_token"), - None, - ) - .unwrap(); - - // SUCCESSFULLY INITIALIZES POOL - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let _user2_address = "user2".to_string(); - - // Mint some LP tokens to user#1 - app.execute_contract( - Addr::unchecked("pair_instance".to_string()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user_address.clone(), - amount: Uint128::from(124231343u128), - }, - &[], - ) - .unwrap(); - - // Deposit into Lockup Position - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 1_000_00) - }); - - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Invalid withdrawal request ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(0u128), - duration: 1u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Invalid withdrawal request" - ); - - // ###### ERROR :: LP Token not supported ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: "wrong_terraswap_token_instance".to_string(), - amount: Uint128::from(10u128), - duration: 1u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "astroport_periphery::lockdrop::PoolInfo not found" - ); - - // ###### ERROR :: Invalid lockup position ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(10u128), - duration: 1u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "astroport_periphery::lockdrop::LockupInfoV1 not found" - ); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY WITHDRAW LP TOKENS FROM POOL ###### - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(10000000u128), - duration: 10u64, - }, - &[], - ) - .unwrap(); - - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(0u128), pool_resp.terraswap_amount_in_lockups); - assert_eq!(CUint256::from(0u64), pool_resp.weighted_amount); - - // check User Info - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(0u128), user_resp.total_astro_rewards); - assert_eq!(Uint128::zero(), user_resp.delegated_astro_rewards); - assert_eq!(0, user_resp.lockup_infos.len()); - - // Deposit Again into Lockup - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_token_instance.clone(), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: Uint128::from(10000000u128), - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Amount exceeds maximum allowed withdrawal limit of {} ###### - // First half of withdrawal window - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10350000) - }); - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(5000001u128), - duration: 10u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Amount exceeds maximum allowed withdrawal limit of 5000000" - ); - - // 2nd half of withdrawal window - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10390000) - }); - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(5000001u128), - duration: 10u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Amount exceeds maximum allowed withdrawal limit of 4200000" - ); - - // ###### SUCCESS :: SHOULD SUCCESSFULLY WITHDRAW LP TOKENS FROM POOL ###### - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(4200000u128), - duration: 10u64, - }, - &[], - ) - .unwrap(); - - // check Pool Info - let pool_resp: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - assert_eq!( - Uint128::from(5800000u128), - pool_resp.terraswap_amount_in_lockups - ); - assert_eq!(CUint256::from(10150000u64), pool_resp.weighted_amount); - - // check User Info - let user_resp: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(1000000000u128), user_resp.total_astro_rewards); - assert_eq!(1, user_resp.lockup_infos.len()); - assert_eq!(1, user_resp.lockup_infos.len()); - assert_eq!( - Uint128::from(5800000u128), - user_resp.lockup_infos[0].lp_units_locked - ); - assert_eq!(true, user_resp.lockup_infos[0].withdrawal_flag); - - // ###### ERROR :: Amount exceeds maximum allowed withdrawal limit of {} ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &ExecuteMsg::WithdrawFromLockup { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - amount: Uint128::from(1u128), - duration: 10u64, - }, - &[], - ) - .unwrap_err(); - assert_eq!( - err.root_cause().to_string(), - "Generic error: Withdrawal already happened. No more withdrawals accepted" - ); -} - -#[test] -fn test_migrate_liquidity() { - let owner = Addr::unchecked("contract_owner"); - let mut app = mock_app(); - - let (_, lockdrop_instance, astroport_factory_instance, _, _) = - instantiate_all_contracts(&mut app, owner.clone()); - - // CW20 TOKEN :: Dummy token - let cw20_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let cw20_code_id = app.store_code(cw20_contract); - - let anc_instance = app - .instantiate_contract( - cw20_code_id, - owner.clone(), - &TokenInstantiateMsg { - name: String::from("ANC"), - symbol: String::from("ANC"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }, - &[], - String::from("ANC"), - None, - ) - .unwrap(); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - // Terraswap Pair - let terraswap_pair_contract = Box::new( - ContractWrapper::new_with_empty( - terraswap_pair::contract::execute, - terraswap_pair::contract::instantiate, - terraswap_pair::contract::query, - ) - .with_reply_empty(terraswap_pair::contract::reply), - ); - let terraswap_pair_code_id = app.store_code(terraswap_pair_contract); - - // LP POOL INSTANCE - let terraswap_pool_instance = app - .instantiate_contract( - terraswap_pair_code_id, - Addr::unchecked("user".to_string()), - &terraswap::pair::InstantiateMsg { - asset_infos: [ - terraswap::asset::AssetInfo::Token { - contract_addr: anc_instance.clone().to_string(), - }, - terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - token_code_id: terraswap_token_code_id, - asset_decimals: [6, 6], - }, - &[], - String::from("terraswap_pool"), - None, - ) - .unwrap(); - - // Query LP Token - let pair_response: terraswap::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &terraswap_pool_instance, - &terraswap::pair::QueryMsg::Pair {}, - ) - .unwrap(); - let terraswap_token_instance = pair_response.liquidity_token; - - // SUCCESSFULLY INITIALIZES POOL - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Mint ANC to users - app.execute_contract( - owner.clone(), - anc_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user_address.clone(), - amount: Uint128::from(10000_000000u64), - }, - &[], - ) - .unwrap(); - app.execute_contract( - owner.clone(), - anc_instance.clone(), - &cw20::Cw20ExecuteMsg::Mint { - recipient: user2_address.clone(), - amount: Uint128::from(10000_000000u64), - }, - &[], - ) - .unwrap(); - - // Set UST user balances - app.init_modules(|router, _, storage| { - router - .bank - .init_balance( - storage, - &Addr::unchecked(user_address.clone()), - vec![Coin::new(1000000_000000, "uusd")], - ) - .unwrap(); - router - .bank - .init_balance( - storage, - &Addr::unchecked(user2_address.clone()), - vec![Coin::new(1000000_000000, "uusd")], - ) - .unwrap(); - }); - - // user#1 adds liquidity to Terraswap Pool and locks that in Lockdrop contract - // increase allowance - app.execute_contract( - Addr::unchecked(user_address.clone()), - anc_instance.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: terraswap_pool_instance.clone().to_string(), - amount: Uint128::new(1000_000000), - expires: None, - }, - &[], - ) - .unwrap(); - - // add Liquidity to Terraswap pool - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_pool_instance.clone(), - &terraswap::pair::ExecuteMsg::ProvideLiquidity { - assets: [ - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::Token { - contract_addr: anc_instance.clone().to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - ], - slippage_tolerance: None, - receiver: None, - }, - &[Coin::new(1000_000000, "uusd")], - ) - .unwrap(); - - // Query LP balance - let lp_balance_res: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &terraswap_token_instance.clone(), - &cw20::Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - let user_lp_balance = lp_balance_res.balance; - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 1_000_00) - }); - - // Lock LP Tokens into Lockup Position - app.execute_contract( - Addr::unchecked(user_address.clone()), - Addr::unchecked(terraswap_token_instance.clone()), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: user_lp_balance, - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // Increase timestamp for window closure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // Create Astroport Pair - app.execute_contract( - Addr::unchecked("user"), - astroport_factory_instance.clone(), - &astroport::factory::ExecuteMsg::CreatePair { - asset_infos: [ - astroport::asset::AssetInfo::Token { - contract_addr: anc_instance.clone(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - init_params: None, - pair_type: astroport::factory::PairType::Xyk {}, - }, - &[], - ) - .unwrap(); - - // Query Astroport addresses - let pair_resp: astroport::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &astroport_factory_instance, - &astroport::factory::QueryMsg::Pair { - asset_infos: [ - astroport::asset::AssetInfo::Token { - contract_addr: anc_instance.clone(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - }, - ) - .unwrap(); - let astro_pool_address = pair_resp.contract_addr; - let astro_lp_address = pair_resp.liquidity_token; - - // astro LP token balance (Lockdrop) - let terraswap_balance_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &terraswap_token_instance, - &Cw20QueryMsg::Balance { - address: lockdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - - // Query pool before migration - let pool_resp_before_migration: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - - assert_eq!( - terraswap_balance_resp.balance, - pool_resp_before_migration.terraswap_amount_in_lockups - ); - assert_eq!( - CUint256::from(1750000000u128), - pool_resp_before_migration.weighted_amount - ); - assert_eq!(false, pool_resp_before_migration.is_staked); - assert_eq!(None, pool_resp_before_migration.migration_info); - - // Migrate Liquidity - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &ExecuteMsg::MigrateLiquidity { - terraswap_lp_token: terraswap_token_instance.clone(), - astroport_pool_addr: astro_pool_address.to_string(), - slippage_tolerance: None, - }, - &[], - ) - .unwrap(); - - // astro LP token balance (Lockdrop) - let astro_balance_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address, - &Cw20QueryMsg::Balance { - address: lockdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - - // Query pool after migration - let pool_resp_after_migration: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - - assert_eq!( - pool_resp_before_migration.terraswap_pool, - pool_resp_after_migration.terraswap_pool - ); - assert_eq!( - pool_resp_before_migration.terraswap_amount_in_lockups, - pool_resp_after_migration.terraswap_amount_in_lockups - ); - assert_eq!( - pool_resp_before_migration.incentives_share, - pool_resp_after_migration.incentives_share - ); - - assert_eq!( - pool_resp_before_migration.incentives_share, - pool_resp_after_migration.incentives_share - ); - assert_eq!( - Decimal::zero(), - pool_resp_after_migration.generator_astro_per_share - ); - assert_eq!( - RestrictedVector::default(), - pool_resp_after_migration.generator_proxy_per_share - ); - assert_eq!( - MigrationInfo { - terraswap_migrated_amount: astro_balance_resp.balance, - astroport_lp_token: astro_lp_address - }, - pool_resp_after_migration.migration_info.unwrap() - ); -} - -#[test] -fn test_migrate_liquidity_uusd_uluna_pool() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, astroport_factory_instance, _, _) = - instantiate_all_contracts(&mut app, owner.clone()); - - // Terraswap LP Token - let terraswap_token_contract = Box::new(ContractWrapper::new_with_empty( - cw20_base::contract::execute, - cw20_base::contract::instantiate, - cw20_base::contract::query, - )); - let terraswap_token_code_id = app.store_code(terraswap_token_contract); - - // Terraswap Pair - let terraswap_pair_contract = Box::new( - ContractWrapper::new_with_empty( - terraswap_pair::contract::execute, - terraswap_pair::contract::instantiate, - terraswap_pair::contract::query, - ) - .with_reply_empty(terraswap_pair::contract::reply), - ); - let terraswap_pair_code_id = app.store_code(terraswap_pair_contract); - - // LP POOL INSTANCE - let terraswap_pool_instance = app - .instantiate_contract( - terraswap_pair_code_id, - Addr::unchecked("user".to_string()), - &terraswap::pair::InstantiateMsg { - asset_infos: [ - terraswap::asset::AssetInfo::NativeToken { - denom: "uluna".to_string(), - }, - terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - token_code_id: terraswap_token_code_id, - asset_decimals: [6, 6], - }, - &[], - String::from("terraswap_pool"), - None, - ) - .unwrap(); - - // Query LP Token - let pair_response: terraswap::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &terraswap_pool_instance, - &terraswap::pair::QueryMsg::Pair {}, - ) - .unwrap(); - let terraswap_token_instance = pair_response.liquidity_token; - - // SUCCESSFULLY INITIALIZES POOL - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::InitializePool { - terraswap_lp_token: terraswap_token_instance.to_string(), - incentives_share: 10000000u64, - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Set UST user balances - app.init_modules(|router, _, storage| { - router - .bank - .init_balance( - storage, - &Addr::unchecked(user_address.clone()), - vec![ - Coin::new(1000000_000000, "uusd"), - Coin::new(1000000_000000, "uluna"), - ], - ) - .unwrap(); - router - .bank - .init_balance( - storage, - &Addr::unchecked(user2_address.clone()), - vec![ - Coin::new(1000000_000000, "uusd"), - Coin::new(1000000_000000, "uluna"), - ], - ) - .unwrap(); - }); - - // user#1 adds liquidity to Terraswap Pool and locks that in Lockdrop contract - - // add Liquidity to Terraswap pool - app.execute_contract( - Addr::unchecked(user_address.clone()), - terraswap_pool_instance.clone(), - &terraswap::pair::ExecuteMsg::ProvideLiquidity { - assets: [ - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - terraswap::asset::Asset { - info: terraswap::asset::AssetInfo::NativeToken { - denom: "uluna".to_string(), - }, - amount: Uint128::from(1000_000000u64), - }, - ], - slippage_tolerance: None, - receiver: None, - }, - &[ - Coin::new(1000_000000, "uluna"), - Coin::new(1000_000000, "uusd"), - ], - ) - .unwrap(); - - // Query LP balance - let lp_balance_res: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &terraswap_token_instance.clone(), - &cw20::Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - let user_lp_balance = lp_balance_res.balance; - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 1_000_00) - }); - - // Lock LP Tokens into Lockup Position - app.execute_contract( - Addr::unchecked(user_address.clone()), - Addr::unchecked(terraswap_token_instance.clone()), - &cw20::Cw20ExecuteMsg::Send { - contract: lockdrop_instance.clone().to_string(), - amount: user_lp_balance, - msg: to_binary(&lockdrop::Cw20HookMsg::IncreaseLockup { duration: 10u64 }).unwrap(), - }, - &[], - ) - .unwrap(); - - // Increase timestamp for window closure - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // Create Astroport Pair - app.execute_contract( - Addr::unchecked("user"), - astroport_factory_instance.clone(), - &astroport::factory::ExecuteMsg::CreatePair { - asset_infos: [ - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uluna".to_string(), - }, - ], - init_params: None, - pair_type: astroport::factory::PairType::Xyk {}, - }, - &[], - ) - .unwrap(); - - // Query Astroport addresses - let pair_resp: astroport::asset::PairInfo = app - .wrap() - .query_wasm_smart( - &astroport_factory_instance, - &astroport::factory::QueryMsg::Pair { - asset_infos: [ - astroport::asset::AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - astroport::asset::AssetInfo::NativeToken { - denom: "uluna".to_string(), - }, - ], - }, - ) - .unwrap(); - - let astro_pool_address = pair_resp.contract_addr; - let astro_lp_address = pair_resp.liquidity_token; - - // astro LP token balance (Lockdrop) - let terraswap_balance_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &terraswap_token_instance, - &Cw20QueryMsg::Balance { - address: lockdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - - // Query pool before migration - let pool_resp_before_migration: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - - assert_eq!( - terraswap_balance_resp.balance, - pool_resp_before_migration.terraswap_amount_in_lockups - ); - assert_eq!( - CUint256::from(1750000000u128), - pool_resp_before_migration.weighted_amount - ); - assert_eq!(false, pool_resp_before_migration.is_staked); - assert_eq!(None, pool_resp_before_migration.migration_info); - - // Migrate Liquidity - app.execute_contract( - owner.clone(), - lockdrop_instance.clone(), - &ExecuteMsg::MigrateLiquidity { - terraswap_lp_token: terraswap_token_instance.clone(), - astroport_pool_addr: astro_pool_address.to_string(), - slippage_tolerance: None, - }, - &[], - ) - .unwrap(); - - // astro LP token balance (Lockdrop) - let astro_balance_resp: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address, - &Cw20QueryMsg::Balance { - address: lockdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - - // Query pool after migration - let pool_resp_after_migration: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - - assert_eq!( - pool_resp_before_migration.terraswap_pool, - pool_resp_after_migration.terraswap_pool - ); - assert_eq!( - pool_resp_before_migration.terraswap_amount_in_lockups, - pool_resp_after_migration.terraswap_amount_in_lockups - ); - assert_eq!( - pool_resp_before_migration.incentives_share, - pool_resp_after_migration.incentives_share - ); - - assert_eq!( - pool_resp_before_migration.incentives_share, - pool_resp_after_migration.incentives_share - ); - assert_eq!( - Decimal::zero(), - pool_resp_after_migration.generator_astro_per_share - ); - assert_eq!( - RestrictedVector::default(), - pool_resp_after_migration.generator_proxy_per_share - ); - assert_eq!( - MigrationInfo { - terraswap_migrated_amount: astro_balance_resp.balance, - astroport_lp_token: astro_lp_address - }, - pool_resp_after_migration.migration_info.unwrap() - ); -} - -#[test] -fn test_stake_lp_tokens() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, astroport_factory_instance, _, update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - let cw20_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let cw20_code_id = app.store_code(cw20_contract); - - let token_instance = app - .instantiate_contract( - cw20_code_id, - owner.clone(), - &TokenInstantiateMsg { - name: String::from("ANC"), - symbol: String::from("ANC"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }, - &[], - String::from("ANC"), - None, - ) - .unwrap(); - - // Initialize and migrate liquidity for a pool - let (terraswap_token_instance, astro_lp_address, _) = initialize_and_migrate_liquidity_for_pool( - &mut app, - owner.clone(), - token_instance, - lockdrop_instance.clone(), - astroport_factory_instance, - ); - - // Add pool to ASTRO Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - Addr::unchecked(update_msg.clone().generator_address.unwrap()), - &astroport::generator::ExecuteMsg::SetupPools { - pools: vec![(astro_lp_address.to_string(), Uint128::from(10u128))], - }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Unauthorized ###### - - let err = app - .execute_contract( - Addr::unchecked("not_owner".to_string()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::StakeLpTokens { - terraswap_lp_token: terraswap_token_instance.clone(), - }, - &[], - ) - .unwrap_err(); - - assert_eq!(err.root_cause().to_string(), "Generic error: Unauthorized"); - - // ###### SHOULD SUCCESSFULLY STAKE LP TOKENS WITH GENERATOR ###### - - // astro LP token balance (Lockdrop) - let lockdrop_astro_balance_before_migration: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address, - &Cw20QueryMsg::Balance { - address: lockdrop_instance.clone().to_string(), - }, - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(owner.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::StakeLpTokens { - terraswap_lp_token: terraswap_token_instance.clone(), - }, - &[], - ) - .unwrap(); - - // astro LP token balance (Generator) - let generator_astro_balance_after_migration: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address, - &Cw20QueryMsg::Balance { - address: update_msg.clone().generator_address.unwrap().to_string(), - }, - ) - .unwrap(); - - assert_eq!( - lockdrop_astro_balance_before_migration.balance, - generator_astro_balance_after_migration.balance - ); - - // Query pool after migration - let pool_resp_after_migration: PoolInfo = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::Pool { - terraswap_lp_token: terraswap_token_instance.clone().to_string(), - }, - ) - .unwrap(); - - assert_eq!(true, pool_resp_after_migration.is_staked); -} - -#[test] -fn test_claim_rewards() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, astroport_factory_instance, _, update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - let cw20_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let cw20_code_id = app.store_code(cw20_contract); - - let token_instance = app - .instantiate_contract( - cw20_code_id, - owner.clone(), - &TokenInstantiateMsg { - name: String::from("ANC"), - symbol: String::from("ANC"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }, - &[], - String::from("ANC"), - None, - ) - .unwrap(); - - // Initialize and migrate liquidity for a pool - let (terraswap_token_instance, astro_lp_address, _) = initialize_and_migrate_liquidity_for_pool( - &mut app, - owner.clone(), - token_instance, - lockdrop_instance.clone(), - astroport_factory_instance, - ); - - // Add pool to ASTRO Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - Addr::unchecked(update_msg.clone().generator_address.unwrap()), - &astroport::generator::ExecuteMsg::SetupPools { - pools: vec![(astro_lp_address.to_string(), Uint128::from(10u128))], - }, - &[], - ) - .unwrap(); - - // Stake LP Tokens with Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::StakeLpTokens { - terraswap_lp_token: terraswap_token_instance.clone(), - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(false, user_info.astro_transferred); - assert_eq!(Uint128::zero(), user_info.delegated_astro_rewards); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(0u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // DELEGATE ASTRO TO AUCTION - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::DelegateAstroToAuction { - amount: Uint128::from(500000000u64), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(user2_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::DelegateAstroToAuction { - amount: Uint128::from(1000u64), - }, - &[], - ) - .unwrap(); - - // Query state - let state: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(500001000u64), state.total_astro_delegated); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); - - // DEPOSIT UST INTO AUCTION - app.execute_contract( - Addr::unchecked(user_address.clone()), - Addr::unchecked(update_msg.auction_contract_address.clone().unwrap()), - &astroport_periphery::auction::ExecuteMsg::DepositUst {}, - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(432423u128), - }], - ) - .unwrap(); - - // ###### ERROR :: Reward claim not allowed ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::ClaimRewardsAndOptionallyUnlock { - terraswap_lp_token: terraswap_token_instance.clone(), - duration: 10u64, - withdraw_lp_stake: false, - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - err.root_cause().to_string(), - "Generic error: Reward claim not allowed" - ); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10750001) - }); - - // INITIALIZE ASTRO-UST POOL TO ENABLE CLAIMS - app.execute_contract( - Addr::unchecked(owner.to_string()), - Addr::unchecked(update_msg.auction_contract_address.clone().unwrap()), - &astroport_periphery::auction::ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap(); - - // ###### ERROR :: Invalid Lockup ###### - - let err = app - .execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::ClaimRewardsAndOptionallyUnlock { - terraswap_lp_token: terraswap_token_instance.clone(), - duration: 9u64, - withdraw_lp_stake: false, - }, - &[], - ) - .unwrap_err(); - - assert_eq!( - err.root_cause().to_string(), - "astroport_periphery::lockdrop::LockupInfoV1 not found" - ); - - // ###### SHOULD SUCCESSFULLY CLAIM REWARDS ###### - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); - assert_eq!(false, user_info.astro_transferred); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(172800000000u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - let user1_astro_balance_before: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::ClaimRewardsAndOptionallyUnlock { - terraswap_lp_token: terraswap_token_instance.clone(), - duration: 10u64, - withdraw_lp_stake: false, - }, - &[], - ) - .unwrap(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); - assert_eq!(true, user_info.astro_transferred); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(172800000000u64), - claimable_generator_astro_debt: Uint128::from(0u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - let user1_astro_balance_after: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - - let astro_reward_claimed = - user1_astro_balance_after.balance - user1_astro_balance_before.balance; - assert_eq!( - astro_reward_claimed, - user_info.total_astro_rewards - user_info.delegated_astro_rewards - + Uint128::from(172800000000u64) - ); - - // ###### SHOULD SUCCESSFULLY CLAIM REWARDS :: user-2 ###### - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user2_address.clone(), - }, - ) - .unwrap(); - - let user2_astro_balance_before: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(Uint128::from(1000u64), user_info.delegated_astro_rewards); - assert_eq!(false, user_info.astro_transferred); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(172800000000u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - app.execute_contract( - Addr::unchecked(user2_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::ClaimRewardsAndOptionallyUnlock { - terraswap_lp_token: terraswap_token_instance.clone(), - duration: 10u64, - withdraw_lp_stake: false, - }, - &[], - ) - .unwrap(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user2_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(Uint128::from(1000u64), user_info.delegated_astro_rewards); - assert_eq!(true, user_info.astro_transferred); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(172800000000u64), - claimable_generator_astro_debt: Uint128::from(0u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - let user2_astro_balance_after: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - - let astro_reward_claimed = - user2_astro_balance_after.balance - user2_astro_balance_before.balance; - assert_eq!( - astro_reward_claimed, - user_info.total_astro_rewards - user_info.delegated_astro_rewards - + Uint128::from(172800000000u64) - ); -} - -#[test] -fn test_claim_rewards_and_unlock() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, astroport_factory_instance, _, update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - let cw20_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let cw20_code_id = app.store_code(cw20_contract); - - let token_instance = app - .instantiate_contract( - cw20_code_id, - owner.clone(), - &TokenInstantiateMsg { - name: String::from("ANC"), - symbol: String::from("ANC"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }, - &[], - String::from("ANC"), - None, - ) - .unwrap(); - - // Initialize and migrate liquidity for a pool - let (terraswap_token_instance, astro_lp_address, _) = initialize_and_migrate_liquidity_for_pool( - &mut app, - owner.clone(), - token_instance, - lockdrop_instance.clone(), - astroport_factory_instance, - ); - - // Add pool to ASTRO Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - Addr::unchecked(update_msg.clone().generator_address.unwrap()), - &astroport::generator::ExecuteMsg::SetupPools { - pools: vec![(astro_lp_address.to_string(), Uint128::from(10u128))], - }, - &[], - ) - .unwrap(); - - // Stake LP Tokens with Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::StakeLpTokens { - terraswap_lp_token: terraswap_token_instance.clone(), - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(false, user_info.astro_transferred); - assert_eq!(Uint128::zero(), user_info.delegated_astro_rewards); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(0u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // DELEGATE ASTRO TO AUCTION - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::DelegateAstroToAuction { - amount: Uint128::from(500000000u64), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(user2_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::DelegateAstroToAuction { - amount: Uint128::from(1000u64), - }, - &[], - ) - .unwrap(); - - // Query state - let state: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(500001000u64), state.total_astro_delegated); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); - - // DEPOSIT UST INTO AUCTION - app.execute_contract( - Addr::unchecked(user_address.clone()), - Addr::unchecked(update_msg.auction_contract_address.clone().unwrap()), - &astroport_periphery::auction::ExecuteMsg::DepositUst {}, - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(432423u128), - }], - ) - .unwrap(); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10750001) - }); - - // INITIALIZE ASTRO-UST POOL TO ENABLE CLAIMS - app.execute_contract( - Addr::unchecked(owner.to_string()), - Addr::unchecked(update_msg.auction_contract_address.clone().unwrap()), - &astroport_periphery::auction::ExecuteMsg::InitPool { slippage: None }, - &[], - ) - .unwrap(); - - // ###### SHOULD SUCCESSFULLY CLAIM REWARDS AND UNLOCK ###### - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 16648001) - }); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); - assert_eq!(false, user_info.astro_transferred); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(259200000000u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - let user1_astro_balance_before: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - - let user1_astro_lp_balance_before: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address.clone(), - &Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::ClaimRewardsAndOptionallyUnlock { - terraswap_lp_token: terraswap_token_instance.clone(), - duration: 10u64, - withdraw_lp_stake: true, - }, - &[], - ) - .unwrap(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); - assert_eq!(true, user_info.astro_transferred); - - let user1_astro_balance_after: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - - let user1_astro_lp_balance_after: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address.clone(), - &Cw20QueryMsg::Balance { - address: user_address.clone(), - }, - ) - .unwrap(); - - let astro_reward_claimed = - user1_astro_balance_after.balance - user1_astro_balance_before.balance; - let lp_tokens_withdrawn = - user1_astro_lp_balance_after.balance - user1_astro_lp_balance_before.balance; - assert_eq!( - astro_reward_claimed, - user_info.total_astro_rewards - user_info.delegated_astro_rewards - + Uint128::from(259200000000u64) - ); - assert_eq!(lp_tokens_withdrawn, Uint128::from(1000000000u64)); - - // ###### SHOULD SUCCESSFULLY CLAIM REWARDS :: user-2 ###### - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user2_address.clone(), - }, - ) - .unwrap(); - - let user2_astro_balance_before: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(Uint128::from(1000u64), user_info.delegated_astro_rewards); - assert_eq!(false, user_info.astro_transferred); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(259200000000u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - let user2_astro_lp_balance_before: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address.clone(), - &Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(user2_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::ClaimRewardsAndOptionallyUnlock { - terraswap_lp_token: terraswap_token_instance.clone(), - duration: 10u64, - withdraw_lp_stake: true, - }, - &[], - ) - .unwrap(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user2_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(Uint128::from(1000u64), user_info.delegated_astro_rewards); - assert_eq!(true, user_info.astro_transferred); - - let user2_astro_balance_after: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &update_msg.astro_token_address.clone().unwrap(), - &Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - - let user2_astro_lp_balance_after: cw20::BalanceResponse = app - .wrap() - .query_wasm_smart( - &astro_lp_address.clone(), - &Cw20QueryMsg::Balance { - address: user2_address.clone(), - }, - ) - .unwrap(); - - let astro_reward_claimed = - user2_astro_balance_after.balance - user2_astro_balance_before.balance; - assert_eq!( - astro_reward_claimed, - user_info.total_astro_rewards - user_info.delegated_astro_rewards - + Uint128::from(259200000000u64) - ); - let lp_tokens_withdrawn = - user2_astro_lp_balance_after.balance - user2_astro_lp_balance_before.balance; - assert_eq!(lp_tokens_withdrawn, Uint128::from(1000000000u64)); -} - -#[test] -fn test_delegate_astro_to_auction() { - let mut app = mock_app(); - let owner = Addr::unchecked("contract_owner"); - - let (_, lockdrop_instance, astroport_factory_instance, _, update_msg) = - instantiate_all_contracts(&mut app, owner.clone()); - - let cw20_contract = Box::new(ContractWrapper::new_with_empty( - astroport_token::contract::execute, - astroport_token::contract::instantiate, - astroport_token::contract::query, - )); - - let cw20_code_id = app.store_code(cw20_contract); - - let token_instance = app - .instantiate_contract( - cw20_code_id, - owner.clone(), - &TokenInstantiateMsg { - name: String::from("ANC"), - symbol: String::from("ANC"), - decimals: 6, - initial_balances: vec![], - mint: Some(cw20::MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }, - &[], - String::from("ANC"), - None, - ) - .unwrap(); - - // Initialize and migrate liquidity for a pool - let (terraswap_token_instance, astro_lp_address, _) = initialize_and_migrate_liquidity_for_pool( - &mut app, - owner.clone(), - token_instance, - lockdrop_instance.clone(), - astroport_factory_instance, - ); - - // Add pool to ASTRO Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - Addr::unchecked(update_msg.clone().generator_address.unwrap()), - &astroport::generator::ExecuteMsg::SetupPools { - pools: vec![(astro_lp_address.to_string(), Uint128::from(10u128))], - }, - &[], - ) - .unwrap(); - - // Stake LP Tokens with Generator - app.execute_contract( - Addr::unchecked(owner.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::StakeLpTokens { - terraswap_lp_token: terraswap_token_instance.clone(), - }, - &[], - ) - .unwrap(); - - let user_address = "user".to_string(); - let user2_address = "user2".to_string(); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!(false, user_info.astro_transferred); - assert_eq!(Uint128::zero(), user_info.delegated_astro_rewards); - let lockup_response = astroport_periphery::lockdrop::LockUpInfoResponse { - lp_units_locked: Uint128::from(1000000000u64), - withdrawal_flag: false, - astro_rewards: Uint128::from(500000000u64), - duration: 10u64, - generator_astro_debt: Uint128::from(0u64), - claimable_generator_astro_debt: Uint128::from(0u64), - generator_proxy_debt: RestrictedVector::default(), - claimable_generator_proxy_debt: RestrictedVector::default(), - unlock_timestamp: EPOCH_START + 16648000u64, - astroport_lp_units: Some(Uint128::from(1000000000u64)), - astroport_lp_token: Some(astro_lp_address.clone()), - terraswap_lp_token: Addr::unchecked(terraswap_token_instance.clone()), - astroport_lp_transferred: None, - }; - assert_eq!(lockup_response, user_info.lockup_infos[0]); - - app.update_block(|b| { - b.height += 17280; - b.time = Timestamp::from_seconds(EPOCH_START + 10600001) - }); - - // DELEGATE ASTRO TO AUCTION - app.execute_contract( - Addr::unchecked(user_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::DelegateAstroToAuction { - amount: Uint128::from(500000000u64), - }, - &[], - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked(user2_address.clone()), - lockdrop_instance.clone(), - &astroport_periphery::lockdrop::ExecuteMsg::DelegateAstroToAuction { - amount: Uint128::from(1000u64), - }, - &[], - ) - .unwrap(); - - // Query state - let state: StateResponse = app - .wrap() - .query_wasm_smart(&lockdrop_instance, &QueryMsg::State {}) - .unwrap(); - assert_eq!(Uint128::from(500001000u64), state.total_astro_delegated); - - // Query user - let user_info: UserInfoResponse = app - .wrap() - .query_wasm_smart( - &lockdrop_instance, - &QueryMsg::UserInfo { - address: user_address.clone(), - }, - ) - .unwrap(); - assert_eq!(Uint128::from(500000000u64), user_info.total_astro_rewards); - assert_eq!( - Uint128::from(500000000u64), - user_info.delegated_astro_rewards - ); -} diff --git a/packages/astroport_periphery/src/airdrop.rs b/packages/astroport_periphery/src/airdrop.rs index 1bd70192..cc238fac 100644 --- a/packages/astroport_periphery/src/airdrop.rs +++ b/packages/astroport_periphery/src/airdrop.rs @@ -3,7 +3,7 @@ use cw20::Cw20ReceiveMsg; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct InstantiateMsg { pub owner: Option, pub astro_token_address: String, @@ -46,13 +46,13 @@ pub enum ExecuteMsg { }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum Cw20HookMsg { IncreaseAstroIncentives {}, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { Config {}, @@ -61,7 +61,7 @@ pub enum QueryMsg { HasUserClaimed { address: String }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct Config { /// Account who can update config @@ -81,7 +81,7 @@ pub struct Config { pub are_claims_enabled: bool, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] #[serde(rename_all = "snake_case")] pub struct State { /// Total ASTRO issuance used as airdrop incentives @@ -92,7 +92,7 @@ pub struct State { pub unclaimed_tokens: Uint128, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] #[serde(rename_all = "snake_case")] pub struct UserInfo { /// Total ASTRO airdrop tokens claimable by the user @@ -103,10 +103,10 @@ pub struct UserInfo { pub tokens_withdrawn: bool, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct ClaimResponse { pub is_claimed: bool, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct MigrateMsg {} diff --git a/packages/astroport_periphery/src/auction.rs b/packages/astroport_periphery/src/auction.rs index 1354f425..4ae73d02 100644 --- a/packages/astroport_periphery/src/auction.rs +++ b/packages/astroport_periphery/src/auction.rs @@ -3,7 +3,7 @@ use cw20::Cw20ReceiveMsg; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct InstantiateMsg { pub owner: Option, pub astro_token_address: String, @@ -15,14 +15,14 @@ pub struct InstantiateMsg { pub withdrawal_window: u64, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct UpdateConfigMsg { pub owner: Option, pub astro_ust_pair_address: Option, pub generator_contract: Option, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PoolInfo { /// ASTRO-UST LP Pool address @@ -47,14 +47,14 @@ pub enum ExecuteMsg { Callback(CallbackMsg), } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum Cw20HookMsg { DelegateAstroTokens { user_address: String }, IncreaseAstroIncentives {}, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum CallbackMsg { UpdateStateOnRewardClaim { @@ -81,7 +81,7 @@ impl CallbackMsg { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { Config {}, @@ -89,10 +89,10 @@ pub enum QueryMsg { UserInfo { address: String }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct MigrateMsg {} -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct Config { /// Account who can update config @@ -119,7 +119,7 @@ pub struct Config { pub withdrawal_window: u64, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] #[serde(rename_all = "snake_case")] pub struct State { /// Total ASTRO tokens delegated to the contract by lockdrop participants / airdrop recipients @@ -136,7 +136,7 @@ pub struct State { pub generator_astro_per_share: Decimal, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] #[serde(rename_all = "snake_case")] pub struct UserInfo { /// Total ASTRO Tokens delegated by the user @@ -159,7 +159,7 @@ pub struct UserInfo { pub user_gen_astro_per_share: Decimal, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct UserInfoResponse { /// Total ASTRO Tokens delegated by the user diff --git a/packages/astroport_periphery/src/lockdrop.rs b/packages/astroport_periphery/src/lockdrop.rs index f4209244..65b68986 100644 --- a/packages/astroport_periphery/src/lockdrop.rs +++ b/packages/astroport_periphery/src/lockdrop.rs @@ -7,7 +7,7 @@ use cw20::Cw20ReceiveMsg; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct InstantiateMsg { /// Account which can update config pub owner: Option, @@ -29,7 +29,7 @@ pub struct InstantiateMsg { pub max_positions_per_user: u32, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct UpdateConfigMsg { /// Astroport token address pub astro_token_address: Option, @@ -116,7 +116,7 @@ pub enum ExecuteMsg { ClaimOwnership {}, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum Cw20HookMsg { /// Open a new user position or add to an existing position (Cw20ReceiveMsg) @@ -167,7 +167,7 @@ impl CallbackMsg { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { Config {}, @@ -193,16 +193,16 @@ pub enum QueryMsg { }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct MigrateMsg {} -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct MigrationInfo { pub terraswap_migrated_amount: Uint128, pub astroport_lp_token: Addr, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct Config { /// Account which can update the config pub owner: Addr, @@ -232,7 +232,7 @@ pub struct Config { pub max_positions_per_user: u32, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] pub struct State { /// Total ASTRO incentives share pub total_incentives_share: u64, @@ -261,7 +261,7 @@ pub struct PoolInfo { pub has_asset_rewards: bool, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] pub struct UserInfo { /// Total ASTRO tokens user received as rewards for participation in the lockdrop pub total_astro_rewards: Uint128, @@ -273,7 +273,7 @@ pub struct UserInfo { pub lockup_positions_index: u32, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct LockupInfoV1 { /// Terraswap LP units locked by the user pub lp_units_locked: Uint128, @@ -307,7 +307,7 @@ pub struct LockupInfoV2 { pub unlock_timestamp: u64, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct StateResponse { /// Total ASTRO incentives share pub total_incentives_share: u64, @@ -335,7 +335,7 @@ pub struct UserInfoResponse { pub lockup_positions_index: u32, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct UserInfoWithListResponse { /// Total ASTRO tokens user received as rewards for participation in the lockdrop pub total_astro_rewards: Uint128, @@ -349,7 +349,7 @@ pub struct UserInfoWithListResponse { pub lockup_positions_index: u32, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct LockUpInfoSummary { pub pool_address: String, pub duration: u64, @@ -382,7 +382,7 @@ pub struct LockUpInfoResponse { pub astroport_lp_transferred: Option, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct PendingAssetRewardResponse { pub amount: Uint128, } diff --git a/packages/astroport_periphery/src/simple_airdrop.rs b/packages/astroport_periphery/src/simple_airdrop.rs index 2832a208..a5e4e980 100644 --- a/packages/astroport_periphery/src/simple_airdrop.rs +++ b/packages/astroport_periphery/src/simple_airdrop.rs @@ -3,7 +3,7 @@ use cw20::Cw20ReceiveMsg; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct InstantiateMsg { pub owner: Option, pub astro_token_address: String, @@ -35,13 +35,13 @@ pub enum ExecuteMsg { }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum Cw20HookMsg { IncreaseAstroIncentives {}, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { Config {}, @@ -50,7 +50,7 @@ pub enum QueryMsg { HasUserClaimed { address: String }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct Config { /// Account who can update config @@ -65,7 +65,7 @@ pub struct Config { pub to_timestamp: u64, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct State { /// Total ASTRO issuance used as airdrop incentives @@ -74,21 +74,21 @@ pub struct State { pub unclaimed_tokens: Uint128, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema, Default)] pub struct UserInfo { /// Total ASTRO airdrop tokens claimable by the user pub airdrop_amount: Uint128, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct UserInfoResponse { pub airdrop_amount: Uint128, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct ClaimResponse { pub is_claimed: bool, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct MigrateMsg {}