Skip to content

Commit

Permalink
Merge pull request #24 from octopus-network/v2.3.0-patch
Browse files Browse the repository at this point in the history
Upgrade to v2.3.0
  • Loading branch information
riversyang authored Oct 24, 2022
2 parents 2dad407 + ca5b7c3 commit 7180969
Show file tree
Hide file tree
Showing 43 changed files with 1,389 additions and 694 deletions.
509 changes: 284 additions & 225 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "appchain-anchor-wrapper"
version = "2.2.0"
version = "2.3.0"
authors = ["Octopus Network"]
edition = "2021"

Expand All @@ -24,6 +24,7 @@ mock-appchain-registry = { path = "./mock-appchain-registry" }
mock-oct-token = { path = "./mock-oct-token" }
wrapped-appchain-token = { git = "https://github.com/octopus-network/wrapped-appchain-token.git", branch = "v2.0.0" }
wrapped-appchain-nft = { git = "https://github.com/octopus-network/wrapped-appchain-nft.git", branch = "main" }
octopus-council = { git = "https://github.com/octopus-network/octopus-dao", branch = "v0.2.0" }
tokio = { version = "1.14", features = ["full"] }
workspaces = "0.4"

Expand All @@ -42,4 +43,5 @@ members = [
"mock-appchain-registry",
"mock-oct-token",
"wat-faucet",
"near-vault",
]
2 changes: 1 addition & 1 deletion appchain-anchor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "appchain-anchor"
version = "2.2.0"
version = "2.3.0"
authors = ["Octopus Network"]
edition = "2021"

Expand Down
4 changes: 4 additions & 0 deletions appchain-anchor/src/anchor_viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ impl AnchorViewer for AppchainAnchor {
self.wrapped_appchain_nfts.get().unwrap().to_vec()
}
//
fn get_native_near_token(&self) -> NativeNearToken {
self.native_near_token.get().unwrap()
}
//
fn get_appchain_state(&self) -> AppchainState {
self.appchain_state.clone()
}
Expand Down
47 changes: 46 additions & 1 deletion appchain-anchor/src/assets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
use crate::{types::NearFungibleToken, AppchainAnchor};
use near_sdk::json_types::U128;

pub mod native_near_token;
pub mod near_fungible_tokens;
pub mod wrapped_appchain_nfts;
mod wrapped_appchain_token;
pub mod wrapped_appchain_token;

impl AppchainAnchor {
///
pub fn assert_locked_asset_on_near_side(
&self,
near_fungible_token: Option<(&NearFungibleToken, &U128)>,
native_near_token_amount: &U128,
) {
let near_fungible_tokens = self.near_fungible_tokens.get().unwrap();
let protocol_settings = self.protocol_settings.get().unwrap();
if let Some(near_fungible_token) = near_fungible_token {
assert!(
near_fungible_tokens.total_market_value()
+ near_fungible_tokens.get_market_value_of(
&near_fungible_token.0.metadata.symbol,
near_fungible_token.1 .0
)
<= self.get_market_value_of_staked_oct_token().0
* u128::from(
protocol_settings.maximum_market_value_percent_of_near_fungible_tokens
)
/ 100,
"Too much NEAR fungible token to lock. Return deposit."
);
}
if native_near_token_amount.0 > 0 {
let native_near_token = self.native_near_token.get().unwrap();
assert!(
near_fungible_tokens.total_market_value()
+ (native_near_token.locked_balance.0 + native_near_token_amount.0)
* native_near_token.price_in_usd.0
<= self.get_market_value_of_staked_oct_token().0
* u128::from(
protocol_settings.maximum_market_value_percent_of_near_fungible_tokens
)
/ 100,
"Too much native NEAR token to lock."
);
}
}
}
200 changes: 200 additions & 0 deletions appchain-anchor/src/assets/native_near_token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
use crate::{
interfaces::NativeNearTokenManager, permissionless_actions::AppchainMessagesProcessingContext,
*,
};
use near_sdk::json_types::Base58CryptoHash;
use std::str::FromStr;

pub const PREFIX_OF_RECEIVER_SUB_ACCOUNT: &str = "near-vault";
pub const CONTRACT_ACCOUNT_FOR_NATIVE_NEAR_TOKEN: &str = "NEAR";

impl Default for NativeNearToken {
fn default() -> Self {
Self {
locked_balance: U128::from(0),
bridging_state: BridgingState::Closed,
price_in_usd: U128::from(0),
}
}
}

#[near_bindgen]
impl NativeNearTokenManager for AppchainAnchor {
///
fn deploy_near_vault_contract(&mut self) {
self.assert_owner();
assert!(
env::storage_has_key(&StorageKey::NearVaultContractWasm.into_bytes()),
"Wasm file for deployment is not staged yet."
);
let contract_account = AccountId::from_str(
format!(
"{}.{}",
PREFIX_OF_RECEIVER_SUB_ACCOUNT,
env::current_account_id()
)
.as_str(),
)
.unwrap();
Promise::new(contract_account)
.create_account()
.transfer(NATIVE_NEAR_TOKEN_RECEIVER_CONTRACT_INIT_BALANCE)
.add_full_access_key(self.owner_pk.clone())
.deploy_contract(
env::storage_read(&StorageKey::NearVaultContractWasm.into_bytes()).unwrap(),
)
.function_call(
"new".to_string(),
Vec::new(),
0,
Gas::ONE_TERA.mul(T_GAS_FOR_NATIVE_NEAR_RECEIVER_CONTRACT_INITIALIZATION),
);
}
///
fn set_price_of_native_near_token(&mut self, price: U128) {
self.assert_owner();
let mut native_near_token = self.native_near_token.get().unwrap();
assert!(
native_near_token.price_in_usd.0 != price.0,
"The price is not changed."
);
native_near_token.price_in_usd = price;
self.native_near_token.set(&native_near_token);
}
///
fn open_bridging_of_native_near_token(&mut self) {
self.assert_owner();
let mut native_near_token = self.native_near_token.get().unwrap();
assert!(
!native_near_token.bridging_state.eq(&BridgingState::Active),
"The bridging state is already 'active'."
);
native_near_token.bridging_state = BridgingState::Active;
self.native_near_token.set(&native_near_token);
}
///
fn close_bridging_of_native_near_token(&mut self) {
self.assert_owner();
let mut native_near_token = self.native_near_token.get().unwrap();
assert!(
!native_near_token.bridging_state.eq(&BridgingState::Closed),
"The bridging state is already 'closed'."
);
native_near_token.bridging_state = BridgingState::Closed;
self.native_near_token.set(&native_near_token);
}
///
fn generate_appchain_notification_for_near_deposit(
&mut self,
sender_id_in_near: AccountId,
receiver_id_in_appchain: String,
amount: U128,
) {
assert!(
env::predecessor_account_id().eq(&AccountId::from_str(
format!(
"{}.{}",
PREFIX_OF_RECEIVER_SUB_ACCOUNT,
env::current_account_id()
)
.as_str()
)
.unwrap()),
"Can only be called by native near token receiver account."
);
self.assert_asset_transfer_is_not_paused();
let mut native_near_token = self.native_near_token.get().unwrap();
assert!(
native_near_token.bridging_state.eq(&BridgingState::Active),
"Bridging for native NEAR token is closed."
);
self.assert_locked_asset_on_near_side(None, &amount);
native_near_token.locked_balance =
U128::from(native_near_token.locked_balance.0 + amount.0);
self.native_near_token.set(&native_near_token);
let appchain_notification_history = self.internal_append_appchain_notification(
AppchainNotification::NearFungibleTokenLocked {
contract_account: String::from_str(CONTRACT_ACCOUNT_FOR_NATIVE_NEAR_TOKEN).unwrap(),
sender_id_in_near,
receiver_id_in_appchain: receiver_id_in_appchain.clone(),
amount,
},
);
log!(
"Received native NEAR token. Start transfer to '{}' of appchain. Amount: '{}', Crosschain notification index: '{}'.",
&receiver_id_in_appchain,
&amount.0,
&appchain_notification_history.index.0
);
}
}

impl NativeNearToken {
//
pub fn unlock_near(
&mut self,
receiver_id: &AccountId,
amount: &U128,
processing_context: &mut AppchainMessagesProcessingContext,
) -> MultiTxsOperationProcessingResult {
//
#[derive(near_sdk::serde::Serialize)]
#[serde(crate = "near_sdk::serde")]
struct Input {
receiver_id: AccountId,
amount: U128,
}
let args = Input {
receiver_id: receiver_id.clone(),
amount: amount.clone(),
};
let args = near_sdk::serde_json::to_vec(&args)
.expect("Failed to serialize the cross contract args using JSON.");
let contract_account = AccountId::from_str(
format!(
"{}.{}",
PREFIX_OF_RECEIVER_SUB_ACCOUNT,
env::current_account_id()
)
.as_str(),
)
.unwrap();
Promise::new(contract_account).function_call(
"unlock_near".to_string(),
args,
0,
Gas::ONE_TERA.mul(T_GAS_FOR_UNLOCK_NATIVE_NEAR),
);
processing_context.add_prepaid_gas(Gas::ONE_TERA.mul(T_GAS_FOR_UNLOCK_NATIVE_NEAR));
self.locked_balance = U128::from(self.locked_balance.0 - amount.0);
MultiTxsOperationProcessingResult::Ok
}
}

/// Stores attached data into blob store and returns hash of it.
/// Implemented to avoid loading the data into WASM for optimal gas usage.
#[no_mangle]
pub extern "C" fn store_wasm_of_near_vault_contract() {
env::setup_panic_hook();
let contract: AppchainAnchor = env::state_read().expect("ERR_CONTRACT_IS_NOT_INITIALIZED");
contract.assert_owner();
let input = env::input().expect("ERR_NO_INPUT");
let sha256_hash = env::sha256(&input);

let blob_len = input.len();
let storage_cost = ((blob_len + 32) as u128) * env::storage_byte_cost();
assert!(
env::attached_deposit() >= storage_cost,
"ERR_NOT_ENOUGH_DEPOSIT:{}",
storage_cost
);

env::storage_write(&StorageKey::NearVaultContractWasm.into_bytes(), &input);
let mut blob_hash = [0u8; 32];
blob_hash.copy_from_slice(&sha256_hash);
let blob_hash_str = near_sdk::serde_json::to_string(&Base58CryptoHash::from(blob_hash))
.unwrap()
.into_bytes();

env::value_return(&blob_hash_str);
}
24 changes: 3 additions & 21 deletions appchain-anchor/src/assets/near_fungible_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,26 +232,8 @@ impl AppchainAnchor {
FTDepositMessage::BridgeToAppchain {
receiver_id_in_appchain,
} => {
AccountIdInAppchain::new(
Some(receiver_id_in_appchain.clone()),
&self.appchain_template_type
)
.assert_valid();
let protocol_settings = self.protocol_settings.get().unwrap();
assert!(
near_fungible_tokens.total_market_value()
+ near_fungible_tokens.get_market_value_of(
&near_fungible_token.metadata.symbol,
amount.0
)
<= self.get_market_value_of_staked_oct_token().0
* u128::from(
protocol_settings
.maximum_market_value_percent_of_near_fungible_tokens
)
/ 100,
"Too much NEAR fungible token to lock. Return deposit."
);
AccountIdInAppchain::new(Some(receiver_id_in_appchain.clone()), &self.appchain_template_type).assert_valid();
self.assert_locked_asset_on_near_side(Some((&near_fungible_token, &amount)), &U128::from(0));
near_fungible_token.locked_balance =
match near_fungible_token.locked_balance.0.checked_add(amount.0) {
Some(value) => U128::from(value),
Expand All @@ -260,7 +242,7 @@ impl AppchainAnchor {
near_fungible_tokens.insert(&near_fungible_token);
let appchain_notification_history = self.internal_append_appchain_notification(
AppchainNotification::NearFungibleTokenLocked {
contract_account: near_fungible_token.contract_account.clone(),
contract_account: near_fungible_token.contract_account.to_string(),
sender_id_in_near: sender_id.clone(),
receiver_id_in_appchain: receiver_id_in_appchain.clone(),
amount,
Expand Down
18 changes: 5 additions & 13 deletions appchain-anchor/src/assets/wrapped_appchain_nfts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ impl AppchainAnchor {
.expect("Failed to serialize the cross contract args using JSON.");
Promise::new(wrapped_appchain_nft.contract_account)
.function_call(
"nft_tranfser".to_string(),
"nft_transfer".to_string(),
args,
1,
Gas::ONE_TERA.mul(T_GAS_FOR_NFT_TRANSFER),
Expand Down Expand Up @@ -500,10 +500,12 @@ impl WrappedAppchainNFTContractResolver for AppchainAnchor {
PromiseResult::NotReady => unreachable!(),
PromiseResult::Successful(_) => {
let message = format!(
"NFT '{}' from appchain account '{}' with metadata '{}' is minted.",
"NFT '{}' of class '{}' from appchain account '{}' with metadata '{}' is minted to '{}'.",
instance_id,
class_id,
owner_id_in_appchain,
serde_json::to_string(&token_metadata).unwrap(),
receiver_id_in_near,
);
self.record_appchain_message_processing_result(
&AppchainMessageProcessingResult::Ok {
Expand All @@ -513,21 +515,11 @@ impl WrappedAppchainNFTContractResolver for AppchainAnchor {
);
}
PromiseResult::Failed => {
let wrapped_appchain_nfts = self.wrapped_appchain_nfts.get().unwrap();
let reason = format!(
"Maybe the receiver account '{}' is not registered in contract '{}'.",
receiver_id_in_near,
wrapped_appchain_nfts
.get(&class_id)
.unwrap()
.contract_account,
);
let message = format!(
"Failed to mint NFT '{}' from appchain account '{}' with metadata '{}'. {}",
"Failed to mint NFT '{}' from appchain account '{}' with metadata '{}'. Need to check results of previous actions.",
instance_id,
owner_id_in_appchain,
serde_json::to_string(&token_metadata).unwrap(),
reason
);
self.record_appchain_message_processing_result(
&AppchainMessageProcessingResult::Error {
Expand Down
Loading

0 comments on commit 7180969

Please sign in to comment.