Skip to content

Commit

Permalink
Synchronize the API with Omni Token. (#252)
Browse files Browse the repository at this point in the history
* sync api with omni token

* fmt

* set new controller

* update wasm

* update wasm

* update wasm

* update gas const

* Improve the Omni api integration (#253)

* Add `finish_withdraw_v2`

* Improve the Omni api integration

* Use controller role to set the controller

* update wasms

---------

Co-authored-by: Karim <karim.alabtakh@nearone.org>
  • Loading branch information
olga24912 and karim-en authored Feb 4, 2025
1 parent ce2234a commit fa14b06
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 28 deletions.
1 change: 1 addition & 0 deletions bridge-token-factory/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

96 changes: 77 additions & 19 deletions bridge-token-factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::{UnorderedMap, UnorderedSet};
use near_sdk::json_types::{Base64VecU8, U128};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::serde_json::json;
use near_sdk::{
env, ext_contract, near_bindgen, AccountId, Balance, Gas, PanicOnDefault, Promise,
env, ext_contract, near_bindgen, require, AccountId, Balance, Gas, PanicOnDefault, Promise,
PromiseOrValue, PublicKey, ONE_NEAR,
};

Expand Down Expand Up @@ -54,9 +55,12 @@ const SET_METADATA_GAS: Gas = Gas(Gas::ONE_TERA.0 * 5);
/// Amount of gas used by bridge token to pause withdraw.
const SET_PAUSED_GAS: Gas = Gas(Gas::ONE_TERA.0 * 5);

// Amount of gas used by bridge token to set new controller
const SET_CONTROLLER_GAS: Gas = Gas(Gas::ONE_TERA.0 * 5);

/// Amount of gas used by `upgrade_bridge_token` in the factory, without taking into account
/// the gas consumed by the promise.
const OUTER_UPGRADE_TOKEN_GAS: Gas = Gas(Gas::ONE_TERA.0 * 15);
const OUTER_UPGRADE_TOKEN_GAS: Gas = Gas(Gas::ONE_TERA.0 * 20);

/// Controller storage key.
const CONTROLLER_STORAGE_KEY: &[u8] = b"aCONTROLLER";
Expand All @@ -71,6 +75,14 @@ const TOKEN_TIMESTAMP_MAP_PREFIX: &[u8] = b"aTT";

pub type Mask = u128;

#[derive(Serialize, Deserialize)]
#[serde(crate = "near_sdk::serde")]
pub struct BasicMetadata {
pub name: String,
pub symbol: String,
pub decimals: u8,
}

#[derive(Debug, Eq, PartialEq, BorshSerialize, BorshDeserialize)]
pub enum ResultType {
Withdraw {
Expand All @@ -93,6 +105,7 @@ pub enum Role {
UpgradableCodeStager,
UpgradableCodeDeployer,
ForceWithdrawer,
Controller,
}

#[near_bindgen]
Expand Down Expand Up @@ -155,7 +168,12 @@ pub trait ExtBridgeTokenFactory {

#[ext_contract(ext_bridge_token)]
pub trait ExtBridgeToken {
fn mint(&self, account_id: AccountId, amount: U128);
fn mint(
&self,
account_id: AccountId,
amount: U128,
msg: Option<String>,
) -> PromiseOrValue<U128>;

fn ft_transfer_call(
&mut self,
Expand All @@ -178,6 +196,8 @@ pub trait ExtBridgeToken {
fn set_paused(&mut self, paused: bool);

fn attach_full_access_key(&mut self, public_key: PublicKey) -> Promise;

fn set_controller(&mut self, controller: AccountId);
}

pub fn assert_self() {
Expand Down Expand Up @@ -399,22 +419,10 @@ impl BridgeTokenFactory {
target, message
));

match message {
Some(message) => ext_bridge_token::ext(self.get_bridge_token_account_id(token.clone()))
.with_static_gas(MINT_GAS)
.with_attached_deposit(env::attached_deposit() - required_deposit)
.mint(env::current_account_id(), amount.into())
.then(
ext_bridge_token::ext(self.get_bridge_token_account_id(token))
.with_static_gas(FT_TRANSFER_CALL_GAS)
.with_attached_deposit(1)
.ft_transfer_call(target, amount.into(), None, message),
),
None => ext_bridge_token::ext(self.get_bridge_token_account_id(token))
.with_static_gas(MINT_GAS)
.with_attached_deposit(env::attached_deposit() - required_deposit)
.mint(target, amount.into()),
}
ext_bridge_token::ext(self.get_bridge_token_account_id(token))
.with_static_gas(MINT_GAS + FT_TRANSFER_CALL_GAS)
.with_attached_deposit(env::attached_deposit() - required_deposit)
.mint(target, amount.into(), message)
}

/// Burn given amount of tokens and unlock it on the Ethereum side for the recipient address.
Expand Down Expand Up @@ -447,6 +455,17 @@ impl BridgeTokenFactory {
}
}

#[allow(unused_variables)]
#[result_serializer(borsh)]
pub fn finish_withdraw_v2(
&mut self,
#[serializer(borsh)] sender_id: AccountId,
#[serializer(borsh)] amount: Balance,
#[serializer(borsh)] recipient: String,
) -> ResultType {
self.finish_withdraw(amount, recipient)
}

#[access_control_any(roles(Role::DAO, Role::ForceWithdrawer))]
#[result_serializer(borsh)]
pub fn force_withdraw(&self, token: String, amount: U128, recipient: String) -> ResultType {
Expand Down Expand Up @@ -492,6 +511,28 @@ impl BridgeTokenFactory {
)
}

#[payable]
#[access_control_any(roles(Role::Controller))]
pub fn deploy_token(&mut self, account_id: AccountId, metadata: &BasicMetadata) -> Promise {
require!(
env::attached_deposit() >= BRIDGE_TOKEN_INIT_BALANCE,
"ERR_NOT_ENOUGH_ATTACHED_BALANCE"
);

Promise::new(account_id)
.create_account()
.transfer(BRIDGE_TOKEN_INIT_BALANCE)
.deploy_contract(BRIDGE_TOKEN_BINARY.to_vec())
.function_call(
"new".to_string(),
json!({"controller": env::predecessor_account_id(), "metadata": metadata})
.to_string()
.into_bytes(),
NO_DEPOSIT,
BRIDGE_TOKEN_NEW,
)
}

/// Upgrades and migrates the bridge token contract to the current version.
///
/// # Arguments
Expand All @@ -508,6 +549,23 @@ impl BridgeTokenFactory {
)
}

/// Set new controller for the provided tokens
///
/// # Arguments
///
/// * `tokens_account_id`: A list of tokens that need their controller updated.
/// * `new_controller`: New controller for tokens
///
#[access_control_any(roles(Role::Controller))]
pub fn set_controller_for_tokens(&self, tokens_account_id: Vec<AccountId>) {
let new_controller = env::predecessor_account_id();
for token_account_id in tokens_account_id {
ext_bridge_token::ext(token_account_id)
.with_static_gas(SET_CONTROLLER_GAS)
.set_controller(new_controller.clone());
}
}

/// Pause the withdraw method in the bridge token contract.
///
/// # Arguments
Expand Down
1 change: 1 addition & 0 deletions bridge-token/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bridge-token/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ overflow-checks = true
[dependencies]
near-sdk = "4.0.0"
near-contract-standards = "4.0.0"
serde = { version = "*", features = ["derive"] }
63 changes: 54 additions & 9 deletions bridge-token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use near_contract_standards::fungible_token::metadata::{
use near_contract_standards::fungible_token::FungibleToken;
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::serde_json::json;
use near_sdk::{
assert_one_yocto, env, ext_contract, near_bindgen, require, AccountId, Balance, Gas,
Expand All @@ -14,10 +15,17 @@ use near_sdk::{
const FINISH_WITHDRAW_GAS: Gas = Gas(Gas::ONE_TERA.0 * 50);
const OUTER_UPGRADE_GAS: Gas = Gas(Gas::ONE_TERA.0 * 15);
const NO_DEPOSIT: Balance = 0;
const CURRENT_STATE_VERSION: u32 = 1;
const CURRENT_STATE_VERSION: u32 = 2;

pub type Mask = u128;

#[derive(Serialize, Deserialize, Default)]
pub struct BasicMetadata {
pub name: String,
pub symbol: String,
pub decimals: u8,
}

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct BridgeToken {
Expand All @@ -40,12 +48,19 @@ pub trait ExtBridgeTokenFactory {
#[serializer(borsh)] amount: Balance,
#[serializer(borsh)] recipient: String,
) -> Promise;

fn finish_withdraw_v2(
&self,
#[serializer(borsh)] sender_id: AccountId,
#[serializer(borsh)] amount: Balance,
#[serializer(borsh)] recipient: String,
) -> Promise;
}

#[near_bindgen]
impl BridgeToken {
#[init]
pub fn new() -> Self {
pub fn new(controller: Option<AccountId>, metadata: Option<BasicMetadata>) -> Self {
let current_account_id = env::current_account_id();
let (_eth_address, factory_account) = current_account_id
.as_str()
Expand All @@ -57,14 +72,15 @@ impl BridgeToken {
"Only the factory account can init this contract"
);

let m = metadata.unwrap_or_default();
Self {
controller: env::predecessor_account_id(),
controller: controller.unwrap_or(env::predecessor_account_id()),
token: FungibleToken::new(b"t".to_vec()),
name: String::default(),
symbol: String::default(),
name: m.name,
symbol: m.symbol,
reference: String::default(),
reference_hash: Base64VecU8(vec![]),
decimals: 0,
decimals: m.decimals,
paused: Mask::default(),
icon: None,
}
Expand All @@ -91,15 +107,39 @@ impl BridgeToken {
}

#[payable]
pub fn mint(&mut self, account_id: AccountId, amount: U128) {
pub fn mint(
&mut self,
account_id: AccountId,
amount: U128,
msg: Option<String>,
) -> PromiseOrValue<U128> {
assert_eq!(
env::predecessor_account_id(),
self.controller,
"Only controller can call mint"
);

self.storage_deposit(Some(account_id.clone()), None);
self.token.internal_deposit(&account_id, amount.into());
if let Some(msg) = msg {
self.token
.internal_deposit(&env::predecessor_account_id(), amount.into());

self.ft_transfer_call(account_id, amount, None, msg)
} else {
self.token.internal_deposit(&account_id, amount.into());
PromiseOrValue::Value(amount)
}
}

pub fn burn(&mut self, amount: U128) {
assert_eq!(
env::predecessor_account_id(),
self.controller,
"Only controller can call burn"
);

self.token
.internal_withdraw(&env::predecessor_account_id(), amount.into());
}

#[payable]
Expand All @@ -113,7 +153,12 @@ impl BridgeToken {

ext_bridge_token_factory::ext(self.controller.clone())
.with_static_gas(FINISH_WITHDRAW_GAS)
.finish_withdraw(amount.into(), recipient)
.finish_withdraw_v2(env::predecessor_account_id(), amount.into(), recipient)
}

pub fn set_controller(&mut self, controller: AccountId) {
require!(self.controller_or_self());
self.controller = controller;
}

pub fn account_storage_usage(&self) -> StorageUsage {
Expand Down
Binary file modified res/bridge_token.wasm
Binary file not shown.
Binary file modified res/bridge_token_factory.wasm
Binary file not shown.

0 comments on commit fa14b06

Please sign in to comment.