From a715c71088875877adba7e87ca5d69cd04a661e9 Mon Sep 17 00:00:00 2001 From: CyberHoward <88450409+CyberHoward@users.noreply.github.com> Date: Fri, 4 Feb 2022 20:16:40 +0100 Subject: [PATCH] [peg-arb] refactor stable-arb-x contracts to one contract and add vault setter (#174) * comment profit-check from workspace to reveal deps * remove dependecy on profit-check contract and integrate logic * add profit queries * fix gov integration test * fix missing Profit save * fix tests * rm profit check from package * rm profit check contract * rm profit check workflow * update toml * Set astroport version to 1.0.0 and rename dapp to prevent conflict * update query to get liquidity token * create pools map to store luna_ust pool addresses * add function to change vault addr * add/fix tests for changes * rename stable-arb-terra to peg-arb and remove astro-arb * update workflow * kerber0x review fixes --- .../{stable_arb_astro.yml => peg-arb.yml} | 4 +- .github/workflows/stable_arb_terra.yml | 59 --- Cargo.toml | 4 +- .../.cargo/config | 0 .../.editorconfig | 0 .../{stable-arb-terra => peg-arb}/Cargo.toml | 4 +- .../examples/schema.rs | 4 +- .../rustfmt.toml | 0 .../schema/execute_msg.json | 66 ++++ .../schema/instantiate_msg.json | 4 - .../schema/query_msg.json | 0 .../schema/state.json | 4 - .../src/contract.rs | 63 ++- .../src/error.rs | 9 +- .../{stable-arb-astro => peg-arb}/src/lib.rs | 0 .../{stable-arb-astro => peg-arb}/src/mock.rs | 0 .../{stable-arb-astro => peg-arb}/src/msg.rs | 9 +- .../src/querier.rs | 0 .../src/response.rs | 0 .../src/state.rs | 4 +- .../src/tests/arb.rs | 4 +- .../src/tests/callback.rs | 3 +- .../src/tests/common.rs | 1 + .../src/tests/flashloan.rs | 4 +- .../src/tests/instantiate.rs | 51 ++- .../src/tests/mock_querier.rs | 0 .../src/tests/mod.rs | 0 contracts/stable-arb-astro/Cargo.toml | 40 -- contracts/stable-arb-astro/examples/schema.rs | 19 - contracts/stable-arb-astro/src/contract.rs | 368 ------------------ contracts/stable-arb-astro/src/state.rs | 21 - contracts/stable-arb-astro/src/tests/arb.rs | 109 ------ .../stable-arb-astro/src/tests/callback.rs | 65 ---- .../stable-arb-astro/src/tests/flashloan.rs | 74 ---- contracts/stable-arb-terra/.cargo/config | 4 - contracts/stable-arb-terra/.editorconfig | 11 - contracts/stable-arb-terra/rustfmt.toml | 15 - .../stable-arb-terra/schema/execute_msg.json | 207 ---------- .../schema/instantiate_msg.json | 72 ---- .../stable-arb-terra/schema/query_msg.json | 18 - contracts/stable-arb-terra/schema/state.json | 27 -- contracts/stable-arb-terra/src/error.rs | 31 -- contracts/stable-arb-terra/src/lib.rs | 10 - contracts/stable-arb-terra/src/mock.rs | 185 --------- contracts/stable-arb-terra/src/msg.rs | 78 ---- contracts/stable-arb-terra/src/querier.rs | 12 - contracts/stable-arb-terra/src/response.rs | 255 ------------ .../stable-arb-terra/src/tests/common.rs | 3 - .../stable-arb-terra/src/tests/instantiate.rs | 89 ----- .../src/tests/mock_querier.rs | 329 ---------------- contracts/stable-arb-terra/src/tests/mod.rs | 6 - 51 files changed, 198 insertions(+), 2147 deletions(-) rename .github/workflows/{stable_arb_astro.yml => peg-arb.yml} (94%) delete mode 100644 .github/workflows/stable_arb_terra.yml rename contracts/{stable-arb-astro => peg-arb}/.cargo/config (100%) rename contracts/{stable-arb-astro => peg-arb}/.editorconfig (100%) rename contracts/{stable-arb-terra => peg-arb}/Cargo.toml (95%) rename contracts/{stable-arb-terra => peg-arb}/examples/schema.rs (83%) rename contracts/{stable-arb-astro => peg-arb}/rustfmt.toml (100%) rename contracts/{stable-arb-astro => peg-arb}/schema/execute_msg.json (78%) rename contracts/{stable-arb-astro => peg-arb}/schema/instantiate_msg.json (95%) rename contracts/{stable-arb-astro => peg-arb}/schema/query_msg.json (100%) rename contracts/{stable-arb-astro => peg-arb}/schema/state.json (93%) rename contracts/{stable-arb-terra => peg-arb}/src/contract.rs (85%) rename contracts/{stable-arb-astro => peg-arb}/src/error.rs (75%) rename contracts/{stable-arb-astro => peg-arb}/src/lib.rs (100%) rename contracts/{stable-arb-astro => peg-arb}/src/mock.rs (100%) rename contracts/{stable-arb-astro => peg-arb}/src/msg.rs (92%) rename contracts/{stable-arb-astro => peg-arb}/src/querier.rs (100%) rename contracts/{stable-arb-astro => peg-arb}/src/response.rs (100%) rename contracts/{stable-arb-terra => peg-arb}/src/state.rs (87%) rename contracts/{stable-arb-terra => peg-arb}/src/tests/arb.rs (96%) rename contracts/{stable-arb-terra => peg-arb}/src/tests/callback.rs (94%) rename contracts/{stable-arb-astro => peg-arb}/src/tests/common.rs (73%) rename contracts/{stable-arb-terra => peg-arb}/src/tests/flashloan.rs (93%) rename contracts/{stable-arb-astro => peg-arb}/src/tests/instantiate.rs (64%) rename contracts/{stable-arb-astro => peg-arb}/src/tests/mock_querier.rs (100%) rename contracts/{stable-arb-astro => peg-arb}/src/tests/mod.rs (100%) delete mode 100644 contracts/stable-arb-astro/Cargo.toml delete mode 100644 contracts/stable-arb-astro/examples/schema.rs delete mode 100644 contracts/stable-arb-astro/src/contract.rs delete mode 100644 contracts/stable-arb-astro/src/state.rs delete mode 100644 contracts/stable-arb-astro/src/tests/arb.rs delete mode 100644 contracts/stable-arb-astro/src/tests/callback.rs delete mode 100644 contracts/stable-arb-astro/src/tests/flashloan.rs delete mode 100644 contracts/stable-arb-terra/.cargo/config delete mode 100644 contracts/stable-arb-terra/.editorconfig delete mode 100644 contracts/stable-arb-terra/rustfmt.toml delete mode 100644 contracts/stable-arb-terra/schema/execute_msg.json delete mode 100644 contracts/stable-arb-terra/schema/instantiate_msg.json delete mode 100644 contracts/stable-arb-terra/schema/query_msg.json delete mode 100644 contracts/stable-arb-terra/schema/state.json delete mode 100644 contracts/stable-arb-terra/src/error.rs delete mode 100644 contracts/stable-arb-terra/src/lib.rs delete mode 100644 contracts/stable-arb-terra/src/mock.rs delete mode 100644 contracts/stable-arb-terra/src/msg.rs delete mode 100644 contracts/stable-arb-terra/src/querier.rs delete mode 100644 contracts/stable-arb-terra/src/response.rs delete mode 100644 contracts/stable-arb-terra/src/tests/common.rs delete mode 100644 contracts/stable-arb-terra/src/tests/instantiate.rs delete mode 100644 contracts/stable-arb-terra/src/tests/mock_querier.rs delete mode 100644 contracts/stable-arb-terra/src/tests/mod.rs diff --git a/.github/workflows/stable_arb_astro.yml b/.github/workflows/peg-arb.yml similarity index 94% rename from .github/workflows/stable_arb_astro.yml rename to .github/workflows/peg-arb.yml index 011d18c2..09eee05f 100644 --- a/.github/workflows/stable_arb_astro.yml +++ b/.github/workflows/peg-arb.yml @@ -1,5 +1,5 @@ -name: Astroport UST Arb +name: Peg Arb on: push: @@ -12,7 +12,7 @@ on: defaults: run: - working-directory: contracts/stable-arb-astro + working-directory: contracts/peg-arb jobs: lint: diff --git a/.github/workflows/stable_arb_terra.yml b/.github/workflows/stable_arb_terra.yml deleted file mode 100644 index d15f62da..00000000 --- a/.github/workflows/stable_arb_terra.yml +++ /dev/null @@ -1,59 +0,0 @@ - -name: Terraswap UST Arb - -on: - push: - branches: - pull_request: - branches: - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -defaults: - run: - working-directory: contracts/stable-arb-terra - -jobs: - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - name: Setup | Checkout - uses: actions/checkout@v2 - - name: Setup | Rust - uses: ATiltedTree/setup-rust@v1 - with: - rust-version: 1.58.1 - components: clippy - - name: Build | Lint - run: cargo clippy -- -D warnings - compile: - name: Compile - runs-on: ubuntu-latest - steps: - - name: Setup | Checkout - uses: actions/checkout@v2 - - name: Setup | Rust - uses: ATiltedTree/setup-rust@v1 - with: - rust-version: stable - - name: Dependencies | Compile - run: cargo update - - name: Build | Compile - run: cargo check - test: - name: Test - runs-on: ubuntu-latest - needs: [compile] - steps: - - name: Setup | Checkout - uses: actions/checkout@v2 - - name: Setup | Rust - uses: ATiltedTree/setup-rust@v1 - with: - rust-version: 1.58.1 - - name: Unit Test | Test - run: cargo unit-test - - name: Schema | Test - run: cargo schema diff --git a/Cargo.toml b/Cargo.toml index 44d4f005..5a8f7006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,7 @@ members = [ "packages/*", "contracts/governance", "contracts/community-fund", - # "contracts/profit-check", - "contracts/stable-arb-terra", - "contracts/stable-arb-astro", + "contracts/peg-arb", "contracts/stablecoin-vault", "contracts/emissions", "contracts/vesting", diff --git a/contracts/stable-arb-astro/.cargo/config b/contracts/peg-arb/.cargo/config similarity index 100% rename from contracts/stable-arb-astro/.cargo/config rename to contracts/peg-arb/.cargo/config diff --git a/contracts/stable-arb-astro/.editorconfig b/contracts/peg-arb/.editorconfig similarity index 100% rename from contracts/stable-arb-astro/.editorconfig rename to contracts/peg-arb/.editorconfig diff --git a/contracts/stable-arb-terra/Cargo.toml b/contracts/peg-arb/Cargo.toml similarity index 95% rename from contracts/stable-arb-terra/Cargo.toml rename to contracts/peg-arb/Cargo.toml index 012fbc25..8ddfa16c 100644 --- a/contracts/stable-arb-terra/Cargo.toml +++ b/contracts/peg-arb/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "stable-arb-terra" +name = "peg-arb" version = "0.1.0" authors = ["CyberHoward", "Kerber0x", "0xFable"] edition = "2018" 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. - "stable-arb-terra.wasm", + "contract.wasm", "hash.txt", ] diff --git a/contracts/stable-arb-terra/examples/schema.rs b/contracts/peg-arb/examples/schema.rs similarity index 83% rename from contracts/stable-arb-terra/examples/schema.rs rename to contracts/peg-arb/examples/schema.rs index 608cacde..5919210b 100644 --- a/contracts/stable-arb-terra/examples/schema.rs +++ b/contracts/peg-arb/examples/schema.rs @@ -3,8 +3,8 @@ use std::fs::create_dir_all; use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; -use stable_arb_terra::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; -use stable_arb_terra::state::State; +use peg_arb::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use peg_arb::state::State; fn main() { let mut out_dir = current_dir().unwrap(); diff --git a/contracts/stable-arb-astro/rustfmt.toml b/contracts/peg-arb/rustfmt.toml similarity index 100% rename from contracts/stable-arb-astro/rustfmt.toml rename to contracts/peg-arb/rustfmt.toml diff --git a/contracts/stable-arb-astro/schema/execute_msg.json b/contracts/peg-arb/schema/execute_msg.json similarity index 78% rename from contracts/stable-arb-astro/schema/execute_msg.json rename to contracts/peg-arb/schema/execute_msg.json index 33b0dec4..0f8ed2b7 100644 --- a/contracts/stable-arb-astro/schema/execute_msg.json +++ b/contracts/peg-arb/schema/execute_msg.json @@ -86,6 +86,68 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "update_pools" + ], + "properties": { + "update_pools": { + "type": "object", + "properties": { + "to_add": { + "type": [ + "array", + "null" + ], + "items": { + "type": "array", + "items": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "to_remove": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_vault" + ], + "properties": { + "set_vault": { + "type": "object", + "required": [ + "vault" + ], + "properties": { + "vault": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ @@ -105,6 +167,7 @@ "required": [ "asset", "belief_price", + "pool_name", "slippage" ], "properties": { @@ -114,6 +177,9 @@ "belief_price": { "$ref": "#/definitions/Decimal" }, + "pool_name": { + "type": "string" + }, "slippage": { "$ref": "#/definitions/Decimal" } diff --git a/contracts/stable-arb-astro/schema/instantiate_msg.json b/contracts/peg-arb/schema/instantiate_msg.json similarity index 95% rename from contracts/stable-arb-astro/schema/instantiate_msg.json rename to contracts/peg-arb/schema/instantiate_msg.json index e28ad832..9d69cd4a 100644 --- a/contracts/stable-arb-astro/schema/instantiate_msg.json +++ b/contracts/peg-arb/schema/instantiate_msg.json @@ -4,7 +4,6 @@ "type": "object", "required": [ "asset_info", - "pool_address", "seignorage_address", "vault_address" ], @@ -12,9 +11,6 @@ "asset_info": { "$ref": "#/definitions/AssetInfo" }, - "pool_address": { - "type": "string" - }, "seignorage_address": { "type": "string" }, diff --git a/contracts/stable-arb-astro/schema/query_msg.json b/contracts/peg-arb/schema/query_msg.json similarity index 100% rename from contracts/stable-arb-astro/schema/query_msg.json rename to contracts/peg-arb/schema/query_msg.json diff --git a/contracts/stable-arb-astro/schema/state.json b/contracts/peg-arb/schema/state.json similarity index 93% rename from contracts/stable-arb-astro/schema/state.json rename to contracts/peg-arb/schema/state.json index 104c6258..1d63449a 100644 --- a/contracts/stable-arb-astro/schema/state.json +++ b/contracts/peg-arb/schema/state.json @@ -3,14 +3,10 @@ "title": "State", "type": "object", "required": [ - "pool_address", "seignorage_address", "vault_address" ], "properties": { - "pool_address": { - "$ref": "#/definitions/Addr" - }, "seignorage_address": { "$ref": "#/definitions/Addr" }, diff --git a/contracts/stable-arb-terra/src/contract.rs b/contracts/peg-arb/src/contract.rs similarity index 85% rename from contracts/stable-arb-terra/src/contract.rs rename to contracts/peg-arb/src/contract.rs index fe43798b..d815533a 100644 --- a/contracts/stable-arb-terra/src/contract.rs +++ b/contracts/peg-arb/src/contract.rs @@ -1,6 +1,6 @@ use cosmwasm_std::{ entry_point, to_binary, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, - Response, StdResult, WasmMsg, + Response, StdResult, WasmMsg, Order, }; use terra_cosmwasm::{create_swap_msg, TerraMsgWrapper}; @@ -26,8 +26,8 @@ use crate::msg::{ArbDetails, CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg use crate::querier::query_market_price; -use crate::state::{State, ADMIN, ARB_BASE_ASSET, STATE}; - +use crate::state::{State, ADMIN, ARB_BASE_ASSET, POOLS, STATE}; +use white_whale::memory::LIST_SIZE_LIMIT; type VaultResult = Result, StableArbError>; // version info for migration info @@ -46,7 +46,6 @@ pub fn instantiate( let state = State { vault_address: deps.api.addr_validate(&msg.vault_address)?, seignorage_address: deps.api.addr_validate(&msg.seignorage_address)?, - pool_address: deps.api.addr_validate(&msg.pool_address)?, }; // Store the initial config @@ -78,7 +77,19 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> V Ok(Response::default() .add_attribute("previous admin", previous_admin) .add_attribute("admin", admin)) - } + }, + ExecuteMsg::SetVault { vault } => { + ADMIN.assert_admin(deps.as_ref(), &info.sender)?; + let vault_addr = deps.api.addr_validate(&vault)?; + let mut state = STATE.load(deps.storage)?; + let previous_vault = state.vault_address; + state.vault_address = vault_addr; + STATE.save(deps.storage,&state)?; + Ok(Response::default() + .add_attribute("previous vault", previous_vault) + .add_attribute("vault", vault)) + }, + ExecuteMsg::UpdatePools { to_add, to_remove } => update_pools(deps, to_add, to_remove), ExecuteMsg::Callback(msg) => _handle_callback(deps, env, info, msg), } } @@ -178,6 +189,7 @@ pub fn try_arb_below_peg( } // Set vars + let pool_address = POOLS.load(deps.storage, &details.pool_name)?; let denom = deposit_info.get_denom()?; let lent_coin = deduct_tax( deps.as_ref(), @@ -208,7 +220,7 @@ pub fn try_arb_below_peg( // Terraswap msg, swap LUNA -> STABLE let terraswap_msg = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: state.pool_address.to_string(), + contract_addr: pool_address.to_string(), funds: vec![offer_coin.clone()], msg: to_binary(&create_terraswap_msg( offer_coin, @@ -252,6 +264,7 @@ pub fn try_arb_above_peg( } // Set vars + let pool_address = POOLS.load(deps.storage, &details.pool_name)?; let denom = deposit_info.get_denom()?; let lent_coin = deduct_tax( deps.as_ref(), @@ -267,7 +280,7 @@ pub fn try_arb_above_peg( } // Simulate first tx with Terraswap let expected_luna_received = - simulate_terraswap_swap(deps.as_ref(), state.pool_address.clone(), lent_coin.clone())?; + simulate_terraswap_swap(deps.as_ref(), pool_address.clone(), lent_coin.clone())?; // Construct offer for Market Swap let offer_coin = Coin { @@ -277,7 +290,7 @@ pub fn try_arb_above_peg( // Terraswap msg, swap STABLE -> LUNA let terraswap_msg: CosmosMsg = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: state.pool_address.to_string(), + contract_addr: pool_address.to_string(), funds: vec![lent_coin.clone()], msg: to_binary(&create_terraswap_msg( lent_coin.clone(), @@ -331,6 +344,40 @@ fn after_successful_trade_callback(deps: DepsMut, env: Env) -> VaultResult { }))) } +pub fn update_pools( + deps: DepsMut, + to_add: Option>, + to_remove: Option>, +) -> VaultResult { + + if let Some(pools_to_add) = to_add { + + if POOLS.keys(deps.storage, None, None, Order::Ascending).count() >= LIST_SIZE_LIMIT { + return Err(StableArbError::PoolLimitReached {}); + } + + for (name, new_address) in pools_to_add.into_iter() { + if name.is_empty() { + return Err(StableArbError::EmptyPoolName {}); + }; + // validate addr + POOLS.save( + deps.storage, + name.as_str(), + &deps.api.addr_validate(&new_address)?, + )?; + } + } + + if let Some(pools_to_remove) = to_remove { + for name in pools_to_remove.into_iter() { + POOLS.remove(deps.storage, name.as_str()); + } + } + + Ok(Response::new().add_attribute("action", "update pool addresses")) +} + //---------------------------------------------------------------------------------------- // GOVERNANCE CONTROLLED SETTERS //---------------------------------------------------------------------------------------- diff --git a/contracts/stable-arb-astro/src/error.rs b/contracts/peg-arb/src/error.rs similarity index 75% rename from contracts/stable-arb-astro/src/error.rs rename to contracts/peg-arb/src/error.rs index 4a24c341..5a11eb95 100644 --- a/contracts/stable-arb-astro/src/error.rs +++ b/contracts/peg-arb/src/error.rs @@ -20,11 +20,14 @@ pub enum StableArbError { #[error("Call is not a callback!")] NotCallback {}, - #[error("The requested funds have the wrong denom")] - WrongDenom {}, - #[error("Not enough funds to perform arb-trade")] Broke {}, + + #[error("The name of the proposed pool can not have length 0.")] + EmptyPoolName {}, + + #[error("The pool list has reached its limit, can't store more contracts.")] + PoolLimitReached {}, } impl From for StableArbError { diff --git a/contracts/stable-arb-astro/src/lib.rs b/contracts/peg-arb/src/lib.rs similarity index 100% rename from contracts/stable-arb-astro/src/lib.rs rename to contracts/peg-arb/src/lib.rs diff --git a/contracts/stable-arb-astro/src/mock.rs b/contracts/peg-arb/src/mock.rs similarity index 100% rename from contracts/stable-arb-astro/src/mock.rs rename to contracts/peg-arb/src/mock.rs diff --git a/contracts/stable-arb-astro/src/msg.rs b/contracts/peg-arb/src/msg.rs similarity index 92% rename from contracts/stable-arb-astro/src/msg.rs rename to contracts/peg-arb/src/msg.rs index 0260aed6..597d834a 100644 --- a/contracts/stable-arb-astro/src/msg.rs +++ b/contracts/peg-arb/src/msg.rs @@ -10,7 +10,6 @@ use terraswap::asset::{Asset, AssetInfo}; pub struct InstantiateMsg { pub vault_address: String, pub seignorage_address: String, - pub pool_address: String, pub asset_info: AssetInfo, } @@ -30,6 +29,13 @@ pub enum ExecuteMsg { SetAdmin { admin: String, }, + UpdatePools { + to_add: Option>, + to_remove: Option>, + }, + SetVault { + vault: String, + }, Callback(CallbackMsg), } @@ -59,6 +65,7 @@ pub struct ArbDetails { pub asset: Asset, pub slippage: Decimal, pub belief_price: Decimal, + pub pool_name: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/contracts/stable-arb-astro/src/querier.rs b/contracts/peg-arb/src/querier.rs similarity index 100% rename from contracts/stable-arb-astro/src/querier.rs rename to contracts/peg-arb/src/querier.rs diff --git a/contracts/stable-arb-astro/src/response.rs b/contracts/peg-arb/src/response.rs similarity index 100% rename from contracts/stable-arb-astro/src/response.rs rename to contracts/peg-arb/src/response.rs diff --git a/contracts/stable-arb-terra/src/state.rs b/contracts/peg-arb/src/state.rs similarity index 87% rename from contracts/stable-arb-terra/src/state.rs rename to contracts/peg-arb/src/state.rs index 25160c2d..699dd9f3 100644 --- a/contracts/stable-arb-terra/src/state.rs +++ b/contracts/peg-arb/src/state.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::Addr; use cw_controllers::Admin; -use cw_storage_plus::Item; +use cw_storage_plus::{Item, Map}; use white_whale::deposit_info::ArbBaseAsset; @@ -13,9 +13,9 @@ use white_whale::deposit_info::ArbBaseAsset; pub struct State { pub vault_address: Addr, pub seignorage_address: Addr, - pub pool_address: Addr, } pub const ADMIN: Admin = Admin::new("admin"); pub const STATE: Item = Item::new("\u{0}{5}state"); pub const ARB_BASE_ASSET: Item = Item::new("\u{0}{7}deposit"); +pub const POOLS: Map<&str, Addr> = Map::new("pools"); diff --git a/contracts/stable-arb-terra/src/tests/arb.rs b/contracts/peg-arb/src/tests/arb.rs similarity index 96% rename from contracts/stable-arb-terra/src/tests/arb.rs rename to contracts/peg-arb/src/tests/arb.rs index 224943f0..12be7826 100644 --- a/contracts/stable-arb-terra/src/tests/arb.rs +++ b/contracts/peg-arb/src/tests/arb.rs @@ -1,6 +1,6 @@ use crate::msg::ExecuteMsg; use crate::msg::*; -use crate::tests::common::VAULT_CONTRACT; +use crate::tests::common::{POOL_NAME, VAULT_CONTRACT}; use crate::tests::instantiate::mock_instantiate; use crate::tests::mock_querier::mock_dependencies; use cosmwasm_std::testing::{mock_env, mock_info}; @@ -26,6 +26,7 @@ fn when_given_a_below_peg_msg_then_handle_returns_first_a_mint_then_a_terraswap_ denom: "uusd".to_string(), }, }, + pool_name: POOL_NAME.to_string(), slippage: Decimal::percent(1), belief_price: Decimal::percent(420), }; @@ -74,6 +75,7 @@ fn when_given_an_above_peg_msg_then_handle_returns_first_a_terraswap_then_a_mint denom: "uusd".to_string(), }, }, + pool_name: POOL_NAME.to_string(), slippage: Decimal::percent(1), belief_price: Decimal::percent(420), }; diff --git a/contracts/stable-arb-terra/src/tests/callback.rs b/contracts/peg-arb/src/tests/callback.rs similarity index 94% rename from contracts/stable-arb-terra/src/tests/callback.rs rename to contracts/peg-arb/src/tests/callback.rs index 87b2c5cd..9b79bdf4 100644 --- a/contracts/stable-arb-terra/src/tests/callback.rs +++ b/contracts/peg-arb/src/tests/callback.rs @@ -9,7 +9,7 @@ use terraswap::asset::{Asset, AssetInfo}; use crate::error::StableArbError; use crate::msg::*; -use crate::tests::common::{TEST_CREATOR, VAULT_ASSET}; +use crate::tests::common::{POOL_NAME, TEST_CREATOR, VAULT_ASSET}; use crate::tests::instantiate::mock_instantiate; use crate::tests::mock_querier::mock_dependencies; @@ -47,6 +47,7 @@ fn unsuccessfull_vault_callback() { denom: VAULT_ASSET.to_string(), }, }, + pool_name: POOL_NAME.to_string(), slippage: Decimal::percent(1), belief_price: Decimal::from_str("420").unwrap(), }; diff --git a/contracts/stable-arb-astro/src/tests/common.rs b/contracts/peg-arb/src/tests/common.rs similarity index 73% rename from contracts/stable-arb-astro/src/tests/common.rs rename to contracts/peg-arb/src/tests/common.rs index 2a22360a..0a80a62d 100644 --- a/contracts/stable-arb-astro/src/tests/common.rs +++ b/contracts/peg-arb/src/tests/common.rs @@ -1,3 +1,4 @@ pub(crate) const VAULT_CONTRACT: &str = "vault_contract_address"; pub(crate) const TEST_CREATOR: &str = "creator"; pub(crate) const VAULT_ASSET: &str = "uusd"; +pub(crate) const POOL_NAME: &str = "terraswap_luna_ust"; diff --git a/contracts/stable-arb-terra/src/tests/flashloan.rs b/contracts/peg-arb/src/tests/flashloan.rs similarity index 93% rename from contracts/stable-arb-terra/src/tests/flashloan.rs rename to contracts/peg-arb/src/tests/flashloan.rs index c130c5bf..81af3f68 100644 --- a/contracts/stable-arb-terra/src/tests/flashloan.rs +++ b/contracts/peg-arb/src/tests/flashloan.rs @@ -9,7 +9,7 @@ use terraswap::asset::{Asset, AssetInfo}; use crate::error::StableArbError; use crate::msg::*; -use crate::tests::common::{TEST_CREATOR, VAULT_ASSET}; +use crate::tests::common::{POOL_NAME, TEST_CREATOR, VAULT_ASSET}; use crate::tests::instantiate::mock_instantiate; use crate::tests::mock_querier::mock_dependencies; @@ -28,6 +28,7 @@ fn successfull_flashloan_call() { denom: VAULT_ASSET.to_string(), }, }, + pool_name: POOL_NAME.to_string(), slippage: Decimal::percent(1), belief_price: Decimal::from_str("420").unwrap(), }; @@ -55,6 +56,7 @@ fn unsuccessfull_flashloan_call_wrong_denom() { denom: "ukrt".to_string(), }, }, + pool_name: POOL_NAME.to_string(), slippage: Decimal::percent(1), belief_price: Decimal::from_str("420").unwrap(), }; diff --git a/contracts/stable-arb-astro/src/tests/instantiate.rs b/contracts/peg-arb/src/tests/instantiate.rs similarity index 64% rename from contracts/stable-arb-astro/src/tests/instantiate.rs rename to contracts/peg-arb/src/tests/instantiate.rs index 966b969d..8634c934 100644 --- a/contracts/stable-arb-astro/src/tests/instantiate.rs +++ b/contracts/peg-arb/src/tests/instantiate.rs @@ -13,11 +13,12 @@ use crate::msg::*; use crate::tests::common::{TEST_CREATOR, VAULT_CONTRACT}; use crate::tests::mock_querier::mock_dependencies; +use super::common::POOL_NAME; + pub(crate) fn instantiate_msg() -> InstantiateMsg { InstantiateMsg { vault_address: VAULT_CONTRACT.to_string(), seignorage_address: "seignorage".to_string(), - pool_address: "terraswap_pool".to_string(), asset_info: AssetInfo::NativeToken { denom: "uusd".to_string(), }, @@ -27,19 +28,25 @@ pub(crate) fn instantiate_msg() -> InstantiateMsg { /** * Mocks instantiation. */ -pub fn mock_instantiate(deps: DepsMut) { +pub fn mock_instantiate(mut deps: DepsMut) { let msg = InstantiateMsg { vault_address: VAULT_CONTRACT.to_string(), seignorage_address: "seignorage".to_string(), - pool_address: "terraswap_pool".to_string(), asset_info: AssetInfo::NativeToken { denom: "uusd".to_string(), }, }; let info = mock_info(TEST_CREATOR, &[]); - let _res = instantiate(deps, mock_env(), info, msg) + let _res = instantiate(deps.branch(), mock_env(), info.clone(), msg) .expect("contract successfully handles InstantiateMsg"); + + let add_pool_msg = ExecuteMsg::UpdatePools{ + to_add: Some(vec![(POOL_NAME.to_string(), "terraswap_pool".to_string(), )]), + to_remove: None + }; + + let _res = execute(deps, mock_env(),info, add_pool_msg).unwrap(); } /** @@ -60,7 +67,6 @@ fn successful_initialization() { State { vault_address: deps.api.addr_validate(&VAULT_CONTRACT).unwrap(), seignorage_address: deps.api.addr_validate(&"seignorage").unwrap(), - pool_address: deps.api.addr_validate(&"terraswap_pool").unwrap(), } ); @@ -74,7 +80,7 @@ fn successful_initialization() { } #[test] -fn successfull_set_admin() { +fn successful_set_admin() { let mut deps = mock_dependencies(&[]); mock_instantiate(deps.as_mut()); @@ -87,3 +93,36 @@ fn successfull_set_admin() { let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!(0, res.messages.len()); } + +#[test] +fn successful_set_vault() { + let mut deps = mock_dependencies(&[]); + mock_instantiate(deps.as_mut()); + + // update admin + let info = mock_info(TEST_CREATOR, &[]); + let msg = ExecuteMsg::SetVault { + vault: "new_vault".to_string(), + }; + + let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); + assert_eq!(0, res.messages.len()); +} + +#[test] +fn unsuccessfull_set_vault() { + let mut deps = mock_dependencies(&[]); + mock_instantiate(deps.as_mut()); + + // update admin + let info = mock_info("someone", &[]); + let msg = ExecuteMsg::SetVault { + vault: "new_vault".to_string(), + }; + + let res = execute(deps.as_mut(), mock_env(), info, msg); + match res { + Ok(_) => panic!("caller is not admin, should error"), + Err(_) => () + } +} \ No newline at end of file diff --git a/contracts/stable-arb-astro/src/tests/mock_querier.rs b/contracts/peg-arb/src/tests/mock_querier.rs similarity index 100% rename from contracts/stable-arb-astro/src/tests/mock_querier.rs rename to contracts/peg-arb/src/tests/mock_querier.rs diff --git a/contracts/stable-arb-astro/src/tests/mod.rs b/contracts/peg-arb/src/tests/mod.rs similarity index 100% rename from contracts/stable-arb-astro/src/tests/mod.rs rename to contracts/peg-arb/src/tests/mod.rs diff --git a/contracts/stable-arb-astro/Cargo.toml b/contracts/stable-arb-astro/Cargo.toml deleted file mode 100644 index e31a57b6..00000000 --- a/contracts/stable-arb-astro/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "stable-arb-astro" -version = "0.1.0" -authors = ["CyberHoward", "Kerber0x", "0xFable"] -edition = "2018" - -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. - "stable-arb-astro.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"] - -[dependencies] -cw2 = { version = "0.8" } -cw20 = { version = "0.8" } -cosmwasm-bignumber = "2.2" -cosmwasm-std = { version = "0.16" } -cosmwasm-storage = { version = "0.16" } -cw-storage-plus = { version = "0.8" } -cw-controllers = { version = "0.8" } -schemars = "0.8.1" -serde = { version = "1.0.103", default-features = false, features = ["derive"] } -terra-cosmwasm = "2.2" -terraswap = "2.4.0" -thiserror = { version = "1.0.21" } -white-whale = { version = "1.0.0", path = "../../packages/white_whale" } -protobuf = { version = "2", features = ["with-bytes"] } -semver = "1" - -[dev-dependencies] -cosmwasm-schema = { version = "0.16" } diff --git a/contracts/stable-arb-astro/examples/schema.rs b/contracts/stable-arb-astro/examples/schema.rs deleted file mode 100644 index e05f428c..00000000 --- a/contracts/stable-arb-astro/examples/schema.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::env::current_dir; -use std::fs::create_dir_all; - -use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; - -use stable_arb_astro::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; -use stable_arb_astro::state::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!(State), &out_dir); -} diff --git a/contracts/stable-arb-astro/src/contract.rs b/contracts/stable-arb-astro/src/contract.rs deleted file mode 100644 index 8302c5b2..00000000 --- a/contracts/stable-arb-astro/src/contract.rs +++ /dev/null @@ -1,368 +0,0 @@ -use cosmwasm_std::{ - entry_point, to_binary, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, - Response, StdResult, WasmMsg, -}; - -use terra_cosmwasm::{create_swap_msg, TerraMsgWrapper}; -use terraswap::asset::{Asset, AssetInfo}; - -use terraswap::querier::query_balance; - -use white_whale::denom::LUNA_DENOM; - -use white_whale::astroport_helper::create_astroport_msg; - -use white_whale::deposit_info::ArbBaseAsset; -use white_whale::query::astroport::simulate_swap as simulate_astroport_swap; -use white_whale::tax::deduct_tax; -use white_whale::ust_vault::msg::ExecuteMsg as VaultMsg; -use white_whale::ust_vault::msg::FlashLoanPayload; - -use cw2::{get_contract_version, set_contract_version}; -use semver::Version; - -use crate::error::StableArbError; -use crate::msg::{ArbDetails, CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; - -use crate::querier::query_market_price; - -use crate::state::{State, ADMIN, ARB_BASE_ASSET, STATE}; - -type VaultResult = Result, StableArbError>; - -// version info for migration info -const CONTRACT_NAME: &str = "crates.io:stablecoin-arb-astro"; -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - deps: DepsMut, - _env: Env, - info: MessageInfo, - msg: InstantiateMsg, -) -> VaultResult { - // Use CW2 to set the contract version, this is needed for migrations - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - let state = State { - vault_address: deps.api.addr_validate(&msg.vault_address)?, - seignorage_address: deps.api.addr_validate(&msg.seignorage_address)?, - pool_address: deps.api.addr_validate(&msg.pool_address)?, - }; - - // Store the initial config - STATE.save(deps.storage, &state)?; - ARB_BASE_ASSET.save( - deps.storage, - &ArbBaseAsset { - asset_info: msg.asset_info, - }, - )?; - // Setup the admin as the creator of the contract - ADMIN.set(deps, Some(info.sender))?; - - Ok(Response::default()) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> VaultResult { - match msg { - ExecuteMsg::ExecuteArb { details, above_peg } => { - call_flashloan(deps, env, info, details, above_peg) - } - ExecuteMsg::BelowPegCallback { details } => try_arb_below_peg(deps, env, info, details), - ExecuteMsg::AbovePegCallback { details } => try_arb_above_peg(deps, env, info, details), - ExecuteMsg::SetAdmin { admin } => { - let admin_addr = deps.api.addr_validate(&admin)?; - let previous_admin = ADMIN.get(deps.as_ref())?.unwrap(); - ADMIN.execute_update_admin(deps, info, Some(admin_addr))?; - Ok(Response::default() - .add_attribute("previous admin", previous_admin) - .add_attribute("admin", admin)) - } - ExecuteMsg::Callback(msg) => _handle_callback(deps, env, info, msg), - } -} - -//---------------------------------------------------------------------------------------- -// CONTRACT UPGRADEABILITY -//---------------------------------------------------------------------------------------- - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> VaultResult { - let version: Version = CONTRACT_VERSION.parse()?; - let storage_version: Version = get_contract_version(deps.storage)?.version.parse()?; - - if storage_version < version { - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - - // If state structure changed in any contract version in the way migration is needed, it - // should occur here - } - Ok(Response::default()) -} - -//---------------------------------------------------------------------------------------- -// PRIVATE FUNCTIONS -//---------------------------------------------------------------------------------------- - -fn _handle_callback(deps: DepsMut, env: Env, info: MessageInfo, msg: CallbackMsg) -> VaultResult { - // Callback functions can only be called this contract itself - if info.sender != env.contract.address { - return Err(StableArbError::NotCallback {}); - } - match msg { - CallbackMsg::AfterSuccessfulTradeCallback {} => after_successful_trade_callback(deps, env), - // Possibility to add more callbacks in future. - } -} -//---------------------------------------------------------------------------------------- -// EXECUTE FUNCTION HANDLERS -//---------------------------------------------------------------------------------------- - -fn call_flashloan( - deps: DepsMut, - _env: Env, - _msg_info: MessageInfo, - details: ArbDetails, - above_peg: bool, -) -> VaultResult { - let state = STATE.load(deps.storage)?; - let deposit_info = ARB_BASE_ASSET.load(deps.storage)?; - - // Check if requested asset is same as strategy base asset - deposit_info.assert(&details.asset.info)?; - - // Construct callback msg - let callback_msg = if above_peg { - ExecuteMsg::AbovePegCallback { - details: details.clone(), - } - } else { - ExecuteMsg::BelowPegCallback { - details: details.clone(), - } - }; - - // Construct payload - let payload = FlashLoanPayload { - requested_asset: details.asset, - callback: to_binary(&callback_msg)?, - }; - - // Call stablecoin Vault - Ok( - Response::new().add_message(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: state.vault_address.to_string(), - msg: to_binary(&VaultMsg::FlashLoan { payload })?, - funds: vec![], - })), - ) -} - -// Attempt to perform an arbitrage operation with the assumption that -// the currency to be arb'd is below peg. Needed funds should be provided -// by the earlier stablecoin vault flashloan call. - -pub fn try_arb_below_peg( - deps: DepsMut, - env: Env, - msg_info: MessageInfo, - details: ArbDetails, -) -> VaultResult { - let state = STATE.load(deps.storage)?; - let deposit_info = ARB_BASE_ASSET.load(deps.storage)?; - - // Ensure the caller is the vault - if msg_info.sender != state.vault_address { - return Err(StableArbError::Unauthorized {}); - } - - // Set vars - let denom = deposit_info.get_denom()?; - let lent_coin = deduct_tax( - deps.as_ref(), - Coin::new(details.asset.amount.u128(), denom.clone()), - )?; - let ask_denom = LUNA_DENOM.to_string(); - let response: Response = Response::new(); - - // Check if we have enough funds - let balance = query_balance(&deps.querier, env.contract.address.clone(), denom)?; - if balance < details.asset.amount { - return Err(StableArbError::Broke {}); - } - - // Simulate first tx with Terra Market Module - // lent_coin already takes transfer tax into account. - let expected_luna_received = - query_market_price(deps.as_ref(), lent_coin.clone(), ask_denom.clone())?; - - // Construct offer for Astroport - let offer_coin = Coin { - denom: ask_denom.clone(), - amount: expected_luna_received, - }; - - // Market swap msg, swap STABLE -> LUNA - let swap_msg = create_swap_msg(lent_coin.clone(), ask_denom); - - // Astroport msg, swap LUNA -> STABLE - let astroport_msg = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: state.pool_address.to_string(), - funds: vec![offer_coin.clone()], - msg: to_binary(&create_astroport_msg( - offer_coin, - details.belief_price, - Some(details.slippage), - ))?, - }); - - let logs = vec![ - ("action", String::from("arb below peg")), - ("offer_amount", lent_coin.amount.to_string()), - ("expected_luna", expected_luna_received.to_string()), - ]; - - // Create callback, this will send the funds back to the vault. - let callback_msg = - CallbackMsg::AfterSuccessfulTradeCallback {}.to_cosmos_msg(&env.contract.address)?; - - Ok(response - .add_attributes(logs) - .add_message(swap_msg) - .add_message(astroport_msg) - .add_message(callback_msg)) -} - -// Attempt to perform an arbitrage operation with the assumption that -// the currency to be arb'd is above peg. Needed funds should be provided -// by the earlier stablecoin vault flashloan call. -pub fn try_arb_above_peg( - deps: DepsMut, - env: Env, - msg_info: MessageInfo, - details: ArbDetails, -) -> VaultResult { - let state = STATE.load(deps.storage)?; - let deposit_info = ARB_BASE_ASSET.load(deps.storage)?; - - // Ensure the caller is the vault - if msg_info.sender != state.vault_address { - return Err(StableArbError::Unauthorized {}); - } - - // Set vars - let denom = deposit_info.get_denom()?; - let lent_coin = deduct_tax( - deps.as_ref(), - Coin::new(details.asset.amount.u128(), denom.clone()), - )?; - let ask_denom = LUNA_DENOM.to_string(); - let response: Response = Response::new(); - - // Check if we have enough funds - let balance = query_balance(&deps.querier, env.contract.address.clone(), denom)?; - if balance < details.asset.amount { - return Err(StableArbError::Broke {}); - } - // Simulate first tx with Astroport - let expected_luna_received = - simulate_astroport_swap(deps.as_ref(), state.pool_address.clone(), lent_coin.clone())?; - - // Construct offer for Market Swap - let offer_coin = Coin { - denom: ask_denom, - amount: expected_luna_received, - }; - - // Astroport msg, swap STABLE -> LUNA - let astroport_msg: CosmosMsg = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: state.pool_address.to_string(), - funds: vec![lent_coin.clone()], - msg: to_binary(&create_astroport_msg( - lent_coin.clone(), - details.belief_price, - Some(details.slippage), - ))?, - }); - - // Market swap msg, swap LUNA -> STABLE - let swap_msg = create_swap_msg(offer_coin, lent_coin.denom); - - let logs = vec![ - ("action", String::from("arb above peg")), - ("offer_amount", lent_coin.amount.to_string()), - ("expected_luna", expected_luna_received.to_string()), - ]; - - // Create callback, this will send the funds back to the vault. - let callback_msg = - CallbackMsg::AfterSuccessfulTradeCallback {}.to_cosmos_msg(&env.contract.address)?; - - Ok(response - .add_attributes(logs) - .add_message(astroport_msg) - .add_message(swap_msg) - .add_message(callback_msg)) -} - -//---------------------------------------------------------------------------------------- -// CALLBACK FUNCTION HANDLERS -//---------------------------------------------------------------------------------------- - -// After the arb this function returns the funds to the vault. -fn after_successful_trade_callback(deps: DepsMut, env: Env) -> VaultResult { - let state = STATE.load(deps.storage)?; - let stable_denom = ARB_BASE_ASSET.load(deps.storage)?.get_denom()?; - let stables_in_contract = - query_balance(&deps.querier, env.contract.address, stable_denom.clone())?; - - // Send asset back to vault - let repay_asset = Asset { - info: AssetInfo::NativeToken { - denom: stable_denom, - }, - amount: stables_in_contract, - }; - - Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { - to_address: state.vault_address.to_string(), - amount: vec![repay_asset.deduct_tax(&deps.querier)?], - }))) -} - -//---------------------------------------------------------------------------------------- -// GOVERNANCE CONTROLLED SETTERS -//---------------------------------------------------------------------------------------- - -pub fn set_vault_addr(deps: DepsMut, msg_info: MessageInfo, vault_address: String) -> VaultResult { - // Only the admin should be able to call this - ADMIN.assert_admin(deps.as_ref(), &msg_info.sender)?; - - let mut state = STATE.load(deps.storage)?; - // Get the old vault - let previous_vault = state.vault_address.to_string(); - // Store the new vault addr - state.vault_address = deps.api.addr_validate(&vault_address)?; - STATE.save(deps.storage, &state)?; - // Respond and note the previous vault address - Ok(Response::new() - .add_attribute("new vault", vault_address) - .add_attribute("previous vault", previous_vault)) -} - -//---------------------------------------------------------------------------------------- -// QUERY HANDLERS -//---------------------------------------------------------------------------------------- - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::Config {} => to_binary(&try_query_config(deps)?), - } -} - -pub fn try_query_config(deps: Deps) -> StdResult { - let info: ArbBaseAsset = ARB_BASE_ASSET.load(deps.storage)?; - Ok(info) -} diff --git a/contracts/stable-arb-astro/src/state.rs b/contracts/stable-arb-astro/src/state.rs deleted file mode 100644 index af76f461..00000000 --- a/contracts/stable-arb-astro/src/state.rs +++ /dev/null @@ -1,21 +0,0 @@ -use cosmwasm_std::Addr; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -use cw_controllers::Admin; -use cw_storage_plus::Item; - -use white_whale::deposit_info::ArbBaseAsset; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -// The Arb State contains configuration options for the vault including -// the address of the pool to trade in as well as some other addresses -pub struct State { - pub vault_address: Addr, - pub seignorage_address: Addr, - pub pool_address: Addr, -} - -pub const ADMIN: Admin = Admin::new("admin"); -pub const STATE: Item = Item::new("\u{0}{5}state"); -pub const ARB_BASE_ASSET: Item = Item::new("\u{0}{7}deposit"); diff --git a/contracts/stable-arb-astro/src/tests/arb.rs b/contracts/stable-arb-astro/src/tests/arb.rs deleted file mode 100644 index 224943f0..00000000 --- a/contracts/stable-arb-astro/src/tests/arb.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::msg::ExecuteMsg; -use crate::msg::*; -use crate::tests::common::VAULT_CONTRACT; -use crate::tests::instantiate::mock_instantiate; -use crate::tests::mock_querier::mock_dependencies; -use cosmwasm_std::testing::{mock_env, mock_info}; -use cosmwasm_std::{coins, CosmosMsg, Decimal, Uint128}; -use terra_cosmwasm::TerraRoute; -use terraswap::asset::{Asset, AssetInfo}; - -use crate::contract::execute; -const OFFER_AMOUNT: u64 = 1000u64; - -#[test] -fn when_given_a_below_peg_msg_then_handle_returns_first_a_mint_then_a_terraswap_msg() { - let mut deps = mock_dependencies(&coins(100000000, "uusd")); - mock_instantiate(deps.as_mut()); - - let env = mock_env(); - - // Prepare a Mock Arb Detail object - let arb_detail: ArbDetails = ArbDetails { - asset: Asset { - amount: Uint128::from(OFFER_AMOUNT), - info: AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - }, - slippage: Decimal::percent(1), - belief_price: Decimal::percent(420), - }; - - // Prepare a BelowPegCallback msg - let msg = ExecuteMsg::BelowPegCallback { - details: arb_detail, - }; - - // Ensure the 'caller' is the VAULT_CONTRACT to avoid unauthorized issues - let info = mock_info(VAULT_CONTRACT, &[]); - - let res = execute(deps.as_mut(), env, info, msg).unwrap(); - // We should have gotten 3 messages back in this case - assert_eq!(3, res.messages.len()); - // Verify the operations happened in the order we expect. - // For below peg, we expect first a mint tx, followed by a swap - let first_msg = res.messages[0].msg.clone(); - match first_msg { - CosmosMsg::Bank(_bank_msg) => panic!("unexpected"), - CosmosMsg::Custom(t) => assert_eq!(TerraRoute::Market, t.route), - CosmosMsg::Wasm(_wasm_msg) => panic!("unexpected"), - _ => panic!("unexpected"), - } - let second_msg = res.messages[2].msg.clone(); - match second_msg { - CosmosMsg::Bank(_bank_msg) => panic!("unexpected"), - CosmosMsg::Custom(_t) => panic!("unexpected"), - CosmosMsg::Wasm(_wasm_msg) => {} - _ => panic!("unexpected"), - } -} - -#[test] -fn when_given_an_above_peg_msg_then_handle_returns_first_a_terraswap_then_a_mint_msg() { - let mut deps = mock_dependencies(&coins(100000000, "uusd")); - mock_instantiate(deps.as_mut()); - - let env = mock_env(); - - // Prepare a Mock Arb Detail object - let arb_detail: ArbDetails = ArbDetails { - asset: Asset { - amount: Uint128::from(OFFER_AMOUNT), - info: AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - }, - slippage: Decimal::percent(1), - belief_price: Decimal::percent(420), - }; - - // Prepare an AbovePegCallback msg - let msg = ExecuteMsg::AbovePegCallback { - details: arb_detail, - }; - - // Ensure the 'caller' is the VAULT_CONTRACT to avoid unauthorized issues - let info = mock_info(VAULT_CONTRACT, &[]); - - let res = execute(deps.as_mut(), env, info, msg).unwrap(); - // We should have gotten 3 messages back in this case - assert_eq!(3, res.messages.len()); - // Verify the operations happened in the order we expect. - // For above peg, we expect first terraswap swap tx, followed by a mint - let first_msg = res.messages[0].msg.clone(); - match first_msg { - CosmosMsg::Bank(_bank_msg) => panic!("unexpected"), - CosmosMsg::Custom(_t) => panic!("unexpected"), - CosmosMsg::Wasm(_wasm_msg) => {} - _ => panic!("unexpected"), - } - // Verify the second message is indeed a Market call (to Treasury or otherwise) - let second_msg = res.messages[1].msg.clone(); - match second_msg { - CosmosMsg::Bank(_bank_msg) => panic!("unexpected"), - CosmosMsg::Custom(t) => assert_eq!(TerraRoute::Market, t.route), - CosmosMsg::Wasm(_wasm_msg) => panic!("unexpected"), - _ => panic!("unexpected"), - } -} diff --git a/contracts/stable-arb-astro/src/tests/callback.rs b/contracts/stable-arb-astro/src/tests/callback.rs deleted file mode 100644 index 87b2c5cd..00000000 --- a/contracts/stable-arb-astro/src/tests/callback.rs +++ /dev/null @@ -1,65 +0,0 @@ -use std::str::FromStr; - -use cosmwasm_std::testing::{mock_env, mock_info}; -use cosmwasm_std::{Decimal, Uint128}; - -use crate::contract::execute; - -use terraswap::asset::{Asset, AssetInfo}; - -use crate::error::StableArbError; -use crate::msg::*; -use crate::tests::common::{TEST_CREATOR, VAULT_ASSET}; -use crate::tests::instantiate::mock_instantiate; -use crate::tests::mock_querier::mock_dependencies; - -const OFFER_AMOUNT: u64 = 100_000_000u64; - -#[test] -fn unsuccessfull_self_callback() { - let mut deps = mock_dependencies(&[]); - mock_instantiate(deps.as_mut()); - - let info = mock_info(TEST_CREATOR, &[]); - - let msg = ExecuteMsg::Callback(CallbackMsg::AfterSuccessfulTradeCallback {}); - - let res = execute(deps.as_mut(), mock_env(), info, msg); - match res { - Ok(_) => panic!("Must return error"), - // Caller is not contract itself - Err(StableArbError::NotCallback {}) => (), - Err(_) => panic!("Unknown Error"), - } -} - -#[test] -fn unsuccessfull_vault_callback() { - let mut deps = mock_dependencies(&[]); - mock_instantiate(deps.as_mut()); - - let info = mock_info("some_other_contract", &[]); - - let arb_detail: ArbDetails = ArbDetails { - asset: Asset { - amount: Uint128::from(OFFER_AMOUNT), - info: AssetInfo::NativeToken { - denom: VAULT_ASSET.to_string(), - }, - }, - slippage: Decimal::percent(1), - belief_price: Decimal::from_str("420").unwrap(), - }; - - let msg = ExecuteMsg::AbovePegCallback { - details: arb_detail, - }; - - let res = execute(deps.as_mut(), mock_env(), info, msg); - match res { - Ok(_) => panic!("Must return error"), - // Caller is not the vault - Err(StableArbError::Unauthorized {}) => (), - Err(_) => panic!("Unknown Error"), - } -} diff --git a/contracts/stable-arb-astro/src/tests/flashloan.rs b/contracts/stable-arb-astro/src/tests/flashloan.rs deleted file mode 100644 index c130c5bf..00000000 --- a/contracts/stable-arb-astro/src/tests/flashloan.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::str::FromStr; - -use cosmwasm_std::testing::{mock_env, mock_info}; -use cosmwasm_std::{Decimal, Uint128}; - -use crate::contract::execute; - -use terraswap::asset::{Asset, AssetInfo}; - -use crate::error::StableArbError; -use crate::msg::*; -use crate::tests::common::{TEST_CREATOR, VAULT_ASSET}; -use crate::tests::instantiate::mock_instantiate; -use crate::tests::mock_querier::mock_dependencies; - -const OFFER_AMOUNT: u64 = 100_000_000u64; - -#[test] -fn successfull_flashloan_call() { - let mut deps = mock_dependencies(&[]); - mock_instantiate(deps.as_mut()); - - let info = mock_info(TEST_CREATOR, &[]); - let arb_detail: ArbDetails = ArbDetails { - asset: Asset { - amount: Uint128::from(OFFER_AMOUNT), - info: AssetInfo::NativeToken { - denom: VAULT_ASSET.to_string(), - }, - }, - slippage: Decimal::percent(1), - belief_price: Decimal::from_str("420").unwrap(), - }; - - let msg = ExecuteMsg::ExecuteArb { - details: arb_detail, - above_peg: true, - }; - - let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); - assert_eq!(1, res.messages.len()); -} - -#[test] -fn unsuccessfull_flashloan_call_wrong_denom() { - let mut deps = mock_dependencies(&[]); - mock_instantiate(deps.as_mut()); - - // update admin - let info = mock_info(TEST_CREATOR, &[]); - let arb_detail: ArbDetails = ArbDetails { - asset: Asset { - amount: Uint128::from(OFFER_AMOUNT), - info: AssetInfo::NativeToken { - denom: "ukrt".to_string(), - }, - }, - slippage: Decimal::percent(1), - belief_price: Decimal::from_str("420").unwrap(), - }; - - let msg = ExecuteMsg::ExecuteArb { - details: arb_detail, - above_peg: true, - }; - - let res = execute(deps.as_mut(), mock_env(), info, msg); - match res { - Ok(_) => panic!("Must return error"), - // Throws error from deposit_info.rs - Err(StableArbError::Std(_)) => (), - Err(_) => panic!("Unknown Error"), - } -} diff --git a/contracts/stable-arb-terra/.cargo/config b/contracts/stable-arb-terra/.cargo/config deleted file mode 100644 index 336b618a..00000000 --- a/contracts/stable-arb-terra/.cargo/config +++ /dev/null @@ -1,4 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -unit-test = "test --lib" -schema = "run --example schema" diff --git a/contracts/stable-arb-terra/.editorconfig b/contracts/stable-arb-terra/.editorconfig deleted file mode 100644 index 3d36f20b..00000000 --- a/contracts/stable-arb-terra/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.rs] -indent_size = 4 diff --git a/contracts/stable-arb-terra/rustfmt.toml b/contracts/stable-arb-terra/rustfmt.toml deleted file mode 100644 index 11a85e6a..00000000 --- a/contracts/stable-arb-terra/rustfmt.toml +++ /dev/null @@ -1,15 +0,0 @@ -# stable -newline_style = "unix" -hard_tabs = false -tab_spaces = 4 - -# unstable... should we require `rustup run nightly cargo fmt` ? -# or just update the style guide when they are stable? -#fn_single_line = true -#format_code_in_doc_comments = true -#overflow_delimited_expr = true -#reorder_impl_items = true -#struct_field_align_threshold = 20 -#struct_lit_single_line = true -#report_todo = "Always" - diff --git a/contracts/stable-arb-terra/schema/execute_msg.json b/contracts/stable-arb-terra/schema/execute_msg.json deleted file mode 100644 index 33b0dec4..00000000 --- a/contracts/stable-arb-terra/schema/execute_msg.json +++ /dev/null @@ -1,207 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecuteMsg", - "oneOf": [ - { - "type": "object", - "required": [ - "execute_arb" - ], - "properties": { - "execute_arb": { - "type": "object", - "required": [ - "above_peg", - "details" - ], - "properties": { - "above_peg": { - "type": "boolean" - }, - "details": { - "$ref": "#/definitions/ArbDetails" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "above_peg_callback" - ], - "properties": { - "above_peg_callback": { - "type": "object", - "required": [ - "details" - ], - "properties": { - "details": { - "$ref": "#/definitions/ArbDetails" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "below_peg_callback" - ], - "properties": { - "below_peg_callback": { - "type": "object", - "required": [ - "details" - ], - "properties": { - "details": { - "$ref": "#/definitions/ArbDetails" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "set_admin" - ], - "properties": { - "set_admin": { - "type": "object", - "required": [ - "admin" - ], - "properties": { - "admin": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "callback" - ], - "properties": { - "callback": { - "$ref": "#/definitions/CallbackMsg" - } - }, - "additionalProperties": false - } - ], - "definitions": { - "ArbDetails": { - "type": "object", - "required": [ - "asset", - "belief_price", - "slippage" - ], - "properties": { - "asset": { - "$ref": "#/definitions/Asset" - }, - "belief_price": { - "$ref": "#/definitions/Decimal" - }, - "slippage": { - "$ref": "#/definitions/Decimal" - } - } - }, - "Asset": { - "type": "object", - "required": [ - "amount", - "info" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" - }, - "info": { - "$ref": "#/definitions/AssetInfo" - } - } - }, - "AssetInfo": { - "description": "AssetInfo contract_addr is usually passed from the cw20 hook so we can trust the contract_addr is properly validated.", - "oneOf": [ - { - "type": "object", - "required": [ - "token" - ], - "properties": { - "token": { - "type": "object", - "required": [ - "contract_addr" - ], - "properties": { - "contract_addr": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "native_token" - ], - "properties": { - "native_token": { - "type": "object", - "required": [ - "denom" - ], - "properties": { - "denom": { - "type": "string" - } - } - } - }, - "additionalProperties": false - } - ] - }, - "CallbackMsg": { - "oneOf": [ - { - "type": "object", - "required": [ - "after_successful_trade_callback" - ], - "properties": { - "after_successful_trade_callback": { - "type": "object" - } - }, - "additionalProperties": false - } - ] - }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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/stable-arb-terra/schema/instantiate_msg.json b/contracts/stable-arb-terra/schema/instantiate_msg.json deleted file mode 100644 index e28ad832..00000000 --- a/contracts/stable-arb-terra/schema/instantiate_msg.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InstantiateMsg", - "type": "object", - "required": [ - "asset_info", - "pool_address", - "seignorage_address", - "vault_address" - ], - "properties": { - "asset_info": { - "$ref": "#/definitions/AssetInfo" - }, - "pool_address": { - "type": "string" - }, - "seignorage_address": { - "type": "string" - }, - "vault_address": { - "type": "string" - } - }, - "definitions": { - "AssetInfo": { - "description": "AssetInfo contract_addr is usually passed from the cw20 hook so we can trust the contract_addr is properly validated.", - "oneOf": [ - { - "type": "object", - "required": [ - "token" - ], - "properties": { - "token": { - "type": "object", - "required": [ - "contract_addr" - ], - "properties": { - "contract_addr": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "native_token" - ], - "properties": { - "native_token": { - "type": "object", - "required": [ - "denom" - ], - "properties": { - "denom": { - "type": "string" - } - } - } - }, - "additionalProperties": false - } - ] - } - } -} diff --git a/contracts/stable-arb-terra/schema/query_msg.json b/contracts/stable-arb-terra/schema/query_msg.json deleted file mode 100644 index 3df1ec13..00000000 --- a/contracts/stable-arb-terra/schema/query_msg.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryMsg", - "oneOf": [ - { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "type": "object" - } - }, - "additionalProperties": false - } - ] -} diff --git a/contracts/stable-arb-terra/schema/state.json b/contracts/stable-arb-terra/schema/state.json deleted file mode 100644 index 104c6258..00000000 --- a/contracts/stable-arb-terra/schema/state.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "State", - "type": "object", - "required": [ - "pool_address", - "seignorage_address", - "vault_address" - ], - "properties": { - "pool_address": { - "$ref": "#/definitions/Addr" - }, - "seignorage_address": { - "$ref": "#/definitions/Addr" - }, - "vault_address": { - "$ref": "#/definitions/Addr" - } - }, - "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/stable-arb-terra/src/error.rs b/contracts/stable-arb-terra/src/error.rs deleted file mode 100644 index ab636ab1..00000000 --- a/contracts/stable-arb-terra/src/error.rs +++ /dev/null @@ -1,31 +0,0 @@ -use thiserror::Error; - -use cosmwasm_std::StdError; -use cw_controllers::AdminError; - -#[derive(Error, Debug, PartialEq)] -pub enum StableArbError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("{0}")] - Admin(#[from] AdminError), - - #[error("Semver parsing error: {0}")] - SemVer(String), - - #[error("Unauthorized")] - Unauthorized {}, - - #[error("Call is not a callback!")] - NotCallback {}, - - #[error("Not enough funds to perform arb-trade")] - Broke {}, -} - -impl From for StableArbError { - fn from(err: semver::Error) -> Self { - Self::SemVer(err.to_string()) - } -} diff --git a/contracts/stable-arb-terra/src/lib.rs b/contracts/stable-arb-terra/src/lib.rs deleted file mode 100644 index 446a6195..00000000 --- a/contracts/stable-arb-terra/src/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub mod contract; -pub mod error; -pub mod msg; -pub mod querier; -pub mod response; -pub mod state; - -#[cfg(test)] -#[cfg(not(target_arch = "wasm32"))] -mod tests; diff --git a/contracts/stable-arb-terra/src/mock.rs b/contracts/stable-arb-terra/src/mock.rs deleted file mode 100644 index 0e2064b1..00000000 --- a/contracts/stable-arb-terra/src/mock.rs +++ /dev/null @@ -1,185 +0,0 @@ -// Copied from cosmwasm-std - -use std::collections::HashMap; - -use cosmwasm_std::testing::{MockApi, MockStorage}; -use cosmwasm_std::{ - from_slice, to_binary, AllBalanceResponse, BalanceResponse, BankQuery, Binary, Coin, - ContractResult, Empty, OwnedDeps, Querier, QuerierResult, QueryRequest, SystemError, - SystemResult, Uint128, WasmQuery, -}; - -use terra_cosmwasm::SwapResponse; -use terraswap::pair::SimulationResponse; - -use white_whale::denom::LUNA_DENOM; - -pub const MOCK_CONTRACT_ADDR: &str = "cosmos2contract"; - -/// All external requirements that can be injected for unit tests. -/// It sets the given balance for the contract itself, nothing else -pub fn mock_dependencies( - contract_balance: &[Coin], -) -> OwnedDeps { - OwnedDeps { - storage: MockStorage::default(), - api: MockApi::default(), - querier: MockQuerier::new(&[(&MOCK_CONTRACT_ADDR.to_string(), contract_balance)]), - } -} - -/// MockQuerier holds an immutable table of bank balances -pub struct MockQuerier { - bank: BankQuerier, - // placeholder to add support later - wasm: DummyQuerier, - /// A handler to handle custom queries. This is set to a dummy handler that - /// always errors by default. Update it via `with_custom_handler`. - /// - /// Use box to avoid the need of another generic type - // custom_handler: Box Fn(&'a Empty) -> MockQuerierCustomHandlerResult>, - custom: FakeMarketQuerier, -} - -impl MockQuerier { - pub fn new(balances: &[(&String, &[Coin])]) -> Self { - MockQuerier { - bank: BankQuerier::new(balances), - wasm: DummyQuerier { - pool_address: "test_pool".to_string(), - }, - custom: FakeMarketQuerier {}, - // strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365 - // custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult { - // Ok(Ok(Binary::from(vec![0u8]))) - // // Err(SystemError::UnsupportedRequest { - // // kind: "custom".to_string(), - // // }) - // }), - } - } - - // set a new balance for the given address and return the old balance - pub fn update_balance>( - &mut self, - addr: U, - balance: Vec, - ) -> Option> { - self.bank.balances.insert(addr.into(), balance) - } -} - -impl Querier for MockQuerier { - fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { - let request: QueryRequest = match from_slice(bin_request) { - Ok(v) => v, - Err(e) => { - return SystemResult::Err(SystemError::InvalidRequest { - error: format!("Parsing query request: {}", e), - request: bin_request.into(), - }) - } - }; - self.handle_query(&request) - } -} - -impl MockQuerier { - pub fn handle_query(&self, request: &QueryRequest) -> QuerierResult { - match &request { - QueryRequest::Bank(bank_query) => self.bank.query(bank_query), - QueryRequest::Custom(custom_query) => self.custom.query(custom_query), - QueryRequest::Wasm(msg) => self.wasm.query(msg), - _ => SystemResult::Ok(ContractResult::Ok(to_binary("").unwrap())), - } - } -} - -#[derive(Clone, Default)] -struct DummyQuerier { - pool_address: String, -} - -impl DummyQuerier { - fn process_smart_query(&self, contract_addr: &str) -> QuerierResult { - if contract_addr == self.pool_address { - let binary_response = to_binary(&SimulationResponse { - return_amount: Uint128::from(1000000u64), - spread_amount: Uint128::zero(), - commission_amount: Uint128::zero(), - }); - if binary_response.is_err() { - return SystemResult::Err(SystemError::Unknown {}); - } - - return SystemResult::Ok(ContractResult::Ok(binary_response.unwrap())); - } - - SystemResult::Ok(ContractResult::Ok(Binary::from(vec![0u8]))) - } - - fn query(&self, request: &WasmQuery) -> QuerierResult { - match request { - WasmQuery::Smart { contract_addr, .. } => self.process_smart_query(contract_addr), - _ => SystemResult::Ok(ContractResult::Ok(Binary::from(vec![0u8]))), - } - } -} - -#[derive(Clone, Default)] -struct FakeMarketQuerier {} - -impl FakeMarketQuerier { - fn query(&self, _request: &Empty) -> QuerierResult { - let binary_response = to_binary(&SwapResponse { - receive: Coin { - denom: LUNA_DENOM.to_string(), - amount: Uint128::from(1000000u64), - }, - }); - SystemResult::Ok(ContractResult::Ok(binary_response.unwrap())) - } -} - -#[derive(Clone, Default)] -pub struct BankQuerier { - balances: HashMap>, -} - -impl BankQuerier { - pub fn new(balances: &[(&String, &[Coin])]) -> Self { - let mut map = HashMap::>::new(); - for (addr, coins) in balances.iter() { - map.insert(addr.to_string(), coins.to_vec()); - } - BankQuerier { balances: map } - } - - pub fn query(&self, request: &BankQuery) -> QuerierResult { - match request { - BankQuery::Balance { address, denom } => { - // proper error on not found, serialize result on found - let amount = self - .balances - .get(address) - .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount)) - .unwrap_or_default(); - let bank_res = BalanceResponse { - amount: Coin { - amount, - denom: denom.to_string(), - }, - }; - SystemResult::Ok(ContractResult::Ok(to_binary(&bank_res).unwrap())) - } - BankQuery::AllBalances { address } => { - // proper error on not found, serialize result on found - let bank_res = AllBalanceResponse { - amount: self.balances.get(address).cloned().unwrap_or_default(), - }; - SystemResult::Ok(ContractResult::Ok(to_binary(&bank_res).unwrap())) - } - _ => SystemResult::Ok(ContractResult::Ok(Binary::from(vec![0u8]))), - } - } -} diff --git a/contracts/stable-arb-terra/src/msg.rs b/contracts/stable-arb-terra/src/msg.rs deleted file mode 100644 index 0260aed6..00000000 --- a/contracts/stable-arb-terra/src/msg.rs +++ /dev/null @@ -1,78 +0,0 @@ -use cosmwasm_std::{to_binary, Addr, CosmosMsg, Decimal, StdResult, WasmMsg}; - -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use std::fmt; - -use terraswap::asset::{Asset, AssetInfo}; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InstantiateMsg { - pub vault_address: String, - pub seignorage_address: String, - pub pool_address: String, - pub asset_info: AssetInfo, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ExecuteMsg { - ExecuteArb { - details: ArbDetails, - above_peg: bool, - }, - AbovePegCallback { - details: ArbDetails, - }, - BelowPegCallback { - details: ArbDetails, - }, - SetAdmin { - admin: String, - }, - Callback(CallbackMsg), -} - -// Modified from -// https://github.com/CosmWasm/cosmwasm-plus/blob/v0.2.3/packages/cw20/src/receiver.rs#L15 -impl CallbackMsg { - pub fn to_cosmos_msg( - &self, - contract_addr: &Addr, - ) -> StdResult> { - Ok(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: String::from(contract_addr), - msg: to_binary(&ExecuteMsg::Callback(self.clone()))?, - funds: vec![], - })) - } -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum CallbackMsg { - AfterSuccessfulTradeCallback {}, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ArbDetails { - pub asset: Asset, - pub slippage: Decimal, - pub belief_price: Decimal, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - Config {}, -} - -/// MigrateMsg allows a privileged contract administrator to run -/// a migration on the contract. In this case it is just migrating -/// from one terra code to the same code, but taking advantage of the -/// migration step to set a new validator. -/// -/// Note that the contract doesn't enforce permissions here, this is done -/// by blockchain logic (in the future by blockchain governance) -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct MigrateMsg {} diff --git a/contracts/stable-arb-terra/src/querier.rs b/contracts/stable-arb-terra/src/querier.rs deleted file mode 100644 index a0107209..00000000 --- a/contracts/stable-arb-terra/src/querier.rs +++ /dev/null @@ -1,12 +0,0 @@ -use cosmwasm_std::{Coin, Decimal, Deps, StdResult, Uint128}; -use terra_cosmwasm::TerraQuerier; - -pub fn from_micro(amount: Uint128) -> Decimal { - Decimal::from_ratio(amount, Uint128::from(1000000u64)) -} - -pub fn query_market_price(deps: Deps, offer_coin: Coin, ask_denom: String) -> StdResult { - let querier = TerraQuerier::new(&deps.querier); - let response = querier.query_swap(offer_coin, ask_denom)?; - Ok(response.receive.amount) -} diff --git a/contracts/stable-arb-terra/src/response.rs b/contracts/stable-arb-terra/src/response.rs deleted file mode 100644 index 57e9331c..00000000 --- a/contracts/stable-arb-terra/src/response.rs +++ /dev/null @@ -1,255 +0,0 @@ -// This file is generated by rust-protobuf 2.23.0. Do not edit -// @generated - -// https://github.com/rust-lang/rust-clippy/issues/702 -#![allow(unknown_lints)] -#![allow(clippy::all)] - -#![allow(unused_attributes)] -#![cfg_attr(rustfmt, rustfmt::skip)] - -#![allow(box_pointers)] -#![allow(dead_code)] -#![allow(missing_docs)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(trivial_casts)] -#![allow(unused_imports)] -#![allow(unused_results)] -//! Generated file from `src/response.proto` - -/// Generated files are compatible only with the same version -/// of protobuf runtime. -// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_23_0; - -#[derive(PartialEq,Clone,Default)] -pub struct MsgInstantiateContractResponse { - // message fields - pub contract_address: ::std::string::String, - pub data: ::std::vec::Vec, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a MsgInstantiateContractResponse { - fn default() -> &'a MsgInstantiateContractResponse { - ::default_instance() - } -} - -impl MsgInstantiateContractResponse { - pub fn new() -> MsgInstantiateContractResponse { - ::std::default::Default::default() - } - - // string contract_address = 1; - - - pub fn get_contract_address(&self) -> &str { - &self.contract_address - } - pub fn clear_contract_address(&mut self) { - self.contract_address.clear(); - } - - // Param is passed by value, moved - pub fn set_contract_address(&mut self, v: ::std::string::String) { - self.contract_address = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_contract_address(&mut self) -> &mut ::std::string::String { - &mut self.contract_address - } - - // Take field - pub fn take_contract_address(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.contract_address, ::std::string::String::new()) - } - - // bytes data = 2; - - - pub fn get_data(&self) -> &[u8] { - &self.data - } - pub fn clear_data(&mut self) { - self.data.clear(); - } - - // Param is passed by value, moved - pub fn set_data(&mut self, v: ::std::vec::Vec) { - self.data = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_data(&mut self) -> &mut ::std::vec::Vec { - &mut self.data - } - - // Take field - pub fn take_data(&mut self) -> ::std::vec::Vec { - ::std::mem::replace(&mut self.data, ::std::vec::Vec::new()) - } -} - -impl ::protobuf::Message for MsgInstantiateContractResponse { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.contract_address)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if !self.contract_address.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.contract_address); - } - if !self.data.is_empty() { - my_size += ::protobuf::rt::bytes_size(2, &self.data); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.contract_address.is_empty() { - os.write_string(1, &self.contract_address)?; - } - if !self.data.is_empty() { - os.write_bytes(2, &self.data)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &dyn (::std::any::Any) { - self as &dyn (::std::any::Any) - } - fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { - self as &mut dyn (::std::any::Any) - } - fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> MsgInstantiateContractResponse { - MsgInstantiateContractResponse::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "contract_address", - |m: &MsgInstantiateContractResponse| { &m.contract_address }, - |m: &mut MsgInstantiateContractResponse| { &mut m.contract_address }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "data", - |m: &MsgInstantiateContractResponse| { &m.data }, - |m: &mut MsgInstantiateContractResponse| { &mut m.data }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "MsgInstantiateContractResponse", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static MsgInstantiateContractResponse { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(MsgInstantiateContractResponse::new) - } -} - -impl ::protobuf::Clear for MsgInstantiateContractResponse { - fn clear(&mut self) { - self.contract_address.clear(); - self.data.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for MsgInstantiateContractResponse { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for MsgInstantiateContractResponse { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x12src/response.proto\"_\n\x1eMsgInstantiateContractResponse\x12)\n\ - \x10contract_address\x18\x01\x20\x01(\tR\x0fcontractAddress\x12\x12\n\ - \x04data\x18\x02\x20\x01(\x0cR\x04dataJ\xf8\x02\n\x06\x12\x04\0\0\x08\ - \x03\n\x08\n\x01\x0c\x12\x03\0\0\x12\n_\n\x02\x04\0\x12\x04\x03\0\x08\ - \x03\x1aS\x20MsgInstantiateContractResponse\x20defines\x20the\x20Msg/Ins\ - tantiateContract\x20response\x20type.\n\n\n\n\x03\x04\0\x01\x12\x03\x03\ - \x08&\nR\n\x04\x04\0\x02\0\x12\x03\x05\x04\x20\x1aE\x20ContractAddress\ - \x20is\x20the\x20bech32\x20address\x20of\x20the\x20new\x20contract\x20in\ - stance.\n\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\ - \0\x02\0\x01\x12\x03\x05\x0b\x1b\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x05\ - \x1e\x1f\nO\n\x04\x04\0\x02\x01\x12\x03\x07\x04\x13\x1aB\x20Data\x20cont\ - ains\x20base64-encoded\x20bytes\x20to\x20returned\x20from\x20the\x20cont\ - ract\n\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x07\x04\t\n\x0c\n\x05\x04\0\ - \x02\x01\x01\x12\x03\x07\n\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x07\ - \x11\x12b\x06proto3\ -"; - -static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; - -fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { - ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() -} - -pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { - file_descriptor_proto_lazy.get(|| { - parse_descriptor_proto() - }) -} \ No newline at end of file diff --git a/contracts/stable-arb-terra/src/tests/common.rs b/contracts/stable-arb-terra/src/tests/common.rs deleted file mode 100644 index 2a22360a..00000000 --- a/contracts/stable-arb-terra/src/tests/common.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) const VAULT_CONTRACT: &str = "vault_contract_address"; -pub(crate) const TEST_CREATOR: &str = "creator"; -pub(crate) const VAULT_ASSET: &str = "uusd"; diff --git a/contracts/stable-arb-terra/src/tests/instantiate.rs b/contracts/stable-arb-terra/src/tests/instantiate.rs deleted file mode 100644 index 966b969d..00000000 --- a/contracts/stable-arb-terra/src/tests/instantiate.rs +++ /dev/null @@ -1,89 +0,0 @@ -use cosmwasm_std::testing::{mock_env, mock_info}; -use cosmwasm_std::Api; -use cosmwasm_std::DepsMut; - -use crate::contract::{execute, instantiate}; -use crate::state::{State, ARB_BASE_ASSET, STATE}; - -use terraswap::asset::AssetInfo; - -use white_whale::deposit_info::ArbBaseAsset; - -use crate::msg::*; -use crate::tests::common::{TEST_CREATOR, VAULT_CONTRACT}; -use crate::tests::mock_querier::mock_dependencies; - -pub(crate) fn instantiate_msg() -> InstantiateMsg { - InstantiateMsg { - vault_address: VAULT_CONTRACT.to_string(), - seignorage_address: "seignorage".to_string(), - pool_address: "terraswap_pool".to_string(), - asset_info: AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - } -} - -/** - * Mocks instantiation. - */ -pub fn mock_instantiate(deps: DepsMut) { - let msg = InstantiateMsg { - vault_address: VAULT_CONTRACT.to_string(), - seignorage_address: "seignorage".to_string(), - pool_address: "terraswap_pool".to_string(), - asset_info: AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - }; - - let info = mock_info(TEST_CREATOR, &[]); - let _res = instantiate(deps, mock_env(), info, msg) - .expect("contract successfully handles InstantiateMsg"); -} - -/** - * Tests successful instantiation of the contract. - */ -#[test] -fn successful_initialization() { - let mut deps = mock_dependencies(&[]); - - let msg = instantiate_msg(); - let info = mock_info(TEST_CREATOR, &[]); - let res = instantiate(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); - assert_eq!(0, res.messages.len()); - - let state: State = STATE.load(&deps.storage).unwrap(); - assert_eq!( - state, - State { - vault_address: deps.api.addr_validate(&VAULT_CONTRACT).unwrap(), - seignorage_address: deps.api.addr_validate(&"seignorage").unwrap(), - pool_address: deps.api.addr_validate(&"terraswap_pool").unwrap(), - } - ); - - let base_asset: ArbBaseAsset = ARB_BASE_ASSET.load(&deps.storage).unwrap(); - assert_eq!( - base_asset.asset_info, - AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ); -} - -#[test] -fn successfull_set_admin() { - let mut deps = mock_dependencies(&[]); - mock_instantiate(deps.as_mut()); - - // update admin - let info = mock_info(TEST_CREATOR, &[]); - let msg = ExecuteMsg::SetAdmin { - admin: "new_admin".to_string(), - }; - - let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); - assert_eq!(0, res.messages.len()); -} diff --git a/contracts/stable-arb-terra/src/tests/mock_querier.rs b/contracts/stable-arb-terra/src/tests/mock_querier.rs deleted file mode 100644 index 42c4303c..00000000 --- a/contracts/stable-arb-terra/src/tests/mock_querier.rs +++ /dev/null @@ -1,329 +0,0 @@ -#![allow(dead_code)] -use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage, MOCK_CONTRACT_ADDR}; -use cosmwasm_std::{ - from_binary, from_slice, to_binary, Api, Binary, Coin, ContractResult, Decimal, OwnedDeps, - Querier, QuerierResult, QueryRequest, SystemError, SystemResult, Uint128, WasmQuery, -}; -use cosmwasm_storage::to_length_prefixed; -use cw20::{BalanceResponse as Cw20BalanceResponse, Cw20QueryMsg}; -use std::collections::HashMap; -use terra_cosmwasm::{ - SwapResponse, TaxCapResponse, TaxRateResponse, TerraQuery, TerraQueryWrapper, TerraRoute, -}; -use terraswap::asset::{Asset, AssetInfo, AssetInfoRaw, PairInfo, PairInfoRaw}; -use terraswap::pair::PoolResponse; -use terraswap::pair::SimulationResponse; - -/// mock_dependencies is a drop-in replacement for cosmwasm_std::testing::mock_dependencies -/// this uses our CustomQuerier. -pub fn mock_dependencies( - contract_balance: &[Coin], -) -> OwnedDeps { - let custom_querier: WasmMockQuerier = - WasmMockQuerier::new(MockQuerier::new(&[(MOCK_CONTRACT_ADDR, contract_balance)])); - - OwnedDeps { - api: MockApi::default(), - storage: MockStorage::default(), - querier: custom_querier, - } -} - -pub struct WasmMockQuerier { - base: MockQuerier, - terraswap_pair_querier: TerraswapPairQuerier, - token_querier: TokenQuerier, - tax_querier: TaxQuerier, -} - -#[derive(Clone, Default)] -pub struct TokenQuerier { - // this lets us iterate over all pairs that match the first string - balances: HashMap>, -} - -impl TokenQuerier { - pub fn new(balances: &[(&String, &[(&String, &Uint128)])]) -> Self { - TokenQuerier { - balances: balances_to_map(balances), - } - } -} - -pub(crate) fn balances_to_map( - balances: &[(&String, &[(&String, &Uint128)])], -) -> HashMap> { - let mut balances_map: HashMap> = HashMap::new(); - for (contract_addr, balances) in balances.iter() { - let mut contract_balances_map: HashMap = HashMap::new(); - for (addr, balance) in balances.iter() { - contract_balances_map.insert(addr.to_string(), **balance); - } - - balances_map.insert(contract_addr.to_string(), contract_balances_map); - } - balances_map -} - -#[derive(Clone, Default)] -pub struct TaxQuerier { - rate: Decimal, - // this lets us iterate over all pairs that match the first string - caps: HashMap, -} - -impl TaxQuerier { - pub fn new(rate: Decimal, caps: &[(&String, &Uint128)]) -> Self { - TaxQuerier { - rate, - caps: caps_to_map(caps), - } - } -} - -pub(crate) fn caps_to_map(caps: &[(&String, &Uint128)]) -> HashMap { - let mut owner_map: HashMap = HashMap::new(); - for (denom, cap) in caps.iter() { - owner_map.insert(denom.to_string(), **cap); - } - owner_map -} - -#[derive(Clone, Default)] -pub struct TerraswapPairQuerier { - pairs: HashMap, -} - -impl TerraswapPairQuerier { - pub fn new(pairs: &[(&String, &PairInfo)]) -> Self { - TerraswapPairQuerier { - pairs: pairs_to_map(pairs), - } - } -} - -pub(crate) fn pairs_to_map(pairs: &[(&String, &PairInfo)]) -> HashMap { - let mut pairs_map: HashMap = HashMap::new(); - for (key, pair) in pairs.iter() { - pairs_map.insert(key.to_string(), (*pair).clone()); - } - pairs_map -} - -impl Querier for WasmMockQuerier { - fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { - // MockQuerier doesn't support Custom, so we ignore it completely here - let request: QueryRequest = match from_slice(bin_request) { - Ok(v) => v, - Err(e) => { - return SystemResult::Err(SystemError::InvalidRequest { - error: format!("Parsing query request: {}", e), - request: bin_request.into(), - }) - } - }; - self.handle_query(&request) - } -} - -impl WasmMockQuerier { - pub fn handle_query(&self, request: &QueryRequest) -> QuerierResult { - println!("hello from query"); - println!("{:?}", request); - - match &request { - QueryRequest::Custom(TerraQueryWrapper { route, query_data }) => { - if route == &TerraRoute::Treasury { - match query_data { - TerraQuery::TaxRate {} => { - let res = TaxRateResponse { - rate: self.tax_querier.rate, - }; - SystemResult::Ok(ContractResult::from(to_binary(&res))) - } - TerraQuery::TaxCap { denom } => { - let cap = self - .tax_querier - .caps - .get(denom) - .copied() - .unwrap_or_default(); - let res = TaxCapResponse { cap }; - SystemResult::Ok(ContractResult::from(to_binary(&res))) - } - _ => panic!("DO NOT ENTER HERE"), - } - } else if route == &TerraRoute::Market { - match query_data { - TerraQuery::Swap { - offer_coin, - ask_denom, - } => { - let res = SwapResponse { - receive: Coin { - amount: offer_coin.amount, - denom: String::from(ask_denom), - }, - }; - - SystemResult::Ok(ContractResult::from(to_binary(&res))) - } - _ => panic!("DO NOT ENTER HERE"), - } - } else { - panic!("DO NOT ENTER HERE") - } - } - QueryRequest::Wasm(WasmQuery::Smart { contract_addr, msg }) => { - // Handle calls for Pair Info - - println!("{:?}", request); - - if contract_addr == &String::from("PAIR0000") { - if msg == &Binary::from(r#"{"pool":{}}"#.as_bytes()) { - let msg_pool = PoolResponse { - assets: [ - Asset { - amount: Uint128::from(10000u128), - info: AssetInfo::NativeToken { - denom: "whale".to_string(), - }, - }, - Asset { - amount: Uint128::from(10000u128), - info: AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - }, - ], - total_share: Uint128::from(1000u128), - }; - return SystemResult::Ok(ContractResult::from(to_binary(&msg_pool))); - } - - let msg_balance = PairInfo { - asset_infos: [ - AssetInfo::NativeToken { - denom: "whale".to_string(), - }, - AssetInfo::NativeToken { - denom: "uusd".to_string(), - }, - ], - contract_addr: "PAIR0000".to_string(), - liquidity_token: "liquidity0000".to_string(), - }; - - return SystemResult::Ok(ContractResult::from(to_binary(&msg_balance))); - } - if contract_addr == &String::from("terraswap_pool") { - let binary_response = to_binary(&SimulationResponse { - return_amount: Uint128::from(1000000u64), - spread_amount: Uint128::zero(), - commission_amount: Uint128::zero(), - }); - if binary_response.is_err() { - return SystemResult::Err(SystemError::Unknown {}); - } - - return SystemResult::Ok(ContractResult::Ok(binary_response.unwrap())); - } else { - match from_binary(&msg).unwrap() { - Cw20QueryMsg::Balance { address } => { - let balances: &HashMap = - match self.token_querier.balances.get(contract_addr) { - Some(balances) => balances, - None => { - return SystemResult::Err(SystemError::InvalidRequest { - error: format!( - "No balance info exists for the contract {}", - contract_addr - ), - request: msg.as_slice().into(), - }) - } - }; - - let balance = match balances.get(&address) { - Some(v) => *v, - None => { - return SystemResult::Ok(ContractResult::Ok( - to_binary(&Cw20BalanceResponse { - balance: Uint128::zero(), - }) - .unwrap(), - )); - } - }; - - SystemResult::Ok(ContractResult::Ok( - to_binary(&Cw20BalanceResponse { balance }).unwrap(), - )) - } - _ => panic!("DO NOT ENTER HERE"), - } - } - } - QueryRequest::Wasm(WasmQuery::Raw { contract_addr, key }) => { - let key: &[u8] = key.as_slice(); - let prefix_pair_info = to_length_prefixed(b"pair_info").to_vec(); - - if key.to_vec() == prefix_pair_info { - let pair_info: PairInfo = - match self.terraswap_pair_querier.pairs.get(contract_addr) { - Some(v) => v.clone(), - None => { - return SystemResult::Err(SystemError::InvalidRequest { - error: format!("PairInfo is not found for {}", contract_addr), - request: key.into(), - }) - } - }; - - let api: MockApi = MockApi::default(); - SystemResult::Ok(ContractResult::from(to_binary(&PairInfoRaw { - contract_addr: api - .addr_canonicalize(pair_info.contract_addr.as_str()) - .unwrap(), - liquidity_token: api - .addr_canonicalize(pair_info.liquidity_token.as_str()) - .unwrap(), - asset_infos: [ - AssetInfoRaw::NativeToken { - denom: "uusd".to_string(), - }, - AssetInfoRaw::NativeToken { - denom: "uusd".to_string(), - }, - ], - }))) - } else { - panic!("DO NOT ENTER HERE") - } - } - _ => self.base.handle_query(request), - } - } -} - -impl WasmMockQuerier { - pub fn new(base: MockQuerier) -> Self { - WasmMockQuerier { - base, - terraswap_pair_querier: TerraswapPairQuerier::default(), - token_querier: TokenQuerier::default(), - tax_querier: TaxQuerier::default(), - } - } - - // configure the terraswap pair - pub fn with_terraswap_pairs(&mut self, pairs: &[(&String, &PairInfo)]) { - self.terraswap_pair_querier = TerraswapPairQuerier::new(pairs); - } - - // pub fn with_balance(&mut self, balances: &[(&HumanAddr, &[Coin])]) { - // for (addr, balance) in balances { - // self.base.update_balance(addr, balance.to_vec()); - // } - // } -} diff --git a/contracts/stable-arb-terra/src/tests/mod.rs b/contracts/stable-arb-terra/src/tests/mod.rs deleted file mode 100644 index 55220723..00000000 --- a/contracts/stable-arb-terra/src/tests/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod arb; -mod callback; -mod common; -mod flashloan; -mod instantiate; -mod mock_querier;