Skip to content

Commit

Permalink
fix: refund on error
Browse files Browse the repository at this point in the history
  • Loading branch information
gagdiez committed Oct 11, 2024
1 parent 356a14c commit db79ee0
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
31 changes: 30 additions & 1 deletion src/deploy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata;
use near_sdk::{borsh, env, json_types::U128, near, require, AccountId, NearToken, Promise};
use near_sdk::{borsh, env, json_types::U128, log, near, require, serde_json::json, AccountId, NearToken, Promise, PromiseError};

use crate::{Contract, ContractExt, FT_CONTRACT, NO_DEPOSIT, TGAS};

Expand Down Expand Up @@ -59,6 +59,12 @@ impl Contract {

let init_args = near_sdk::serde_json::to_vec(&args).unwrap();

let user = env::predecessor_account_id();
let callback_args = json!({ "user": user, "deposit": attached })
.to_string()
.into_bytes()
.to_vec();

Promise::new(token_account_id.parse().unwrap())
.create_account()
.transfer(attached)
Expand All @@ -69,5 +75,28 @@ impl Contract {
NO_DEPOSIT,
TGAS.saturating_mul(50),
)
.then(Promise::new(env::current_account_id()).function_call(
"create_callback".to_string(),
callback_args,
NearToken::from_near(0),
TGAS.saturating_mul(30),
))
}

#[private]
pub fn create_callback(
&self,
user: AccountId,
deposit: NearToken,
#[callback_result] call_result: Result<(), PromiseError>,
) -> bool {
match call_result {
Ok(_) => true,
Err(e) => {
log!("Error creating token: {:?}", e);
Promise::new(user).transfer(deposit);
false
}
}
}
}
39 changes: 23 additions & 16 deletions tests/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.transact()
.await?
.into_result()?;

let bob_account = root
.create_subaccount("bob")
.initial_balance(NearToken::from_near(5))
Expand All @@ -50,7 +50,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}

async fn create_token(
contract: &Contract,
factory: &Contract,
token_owner_account: &Account,
alice_account: &Account,
bob_account: &Account,
Expand All @@ -76,48 +76,55 @@ async fn create_token(
};

// Getting required deposit based on provided arguments
let required_deposit: U128 = contract
let required_deposit: U128 = factory
.view("get_required")
.args_json(json!({"args": token_args}))
.await?
.json()?;

// Creating token with less than required deposit (should fail)
let res_0 = contract
.call("create_token")
let not_enough = alice_account
.call(factory.id(), "create_token")
.args_json(json!({"args": token_args}))
.max_gas()
.deposit(NearToken::from_yoctonear(required_deposit.0 - 1))
.transact()
.await?;
assert!(res_0.is_failure());
assert!(not_enough.is_failure());

// Creating token with the required deposit
let res_1 = contract
.call("create_token")
let alice_succeeds = alice_account
.call(factory.id(), "create_token")
.args_json(json!({"args": token_args}))
.max_gas()
.deposit(NearToken::from_yoctonear(required_deposit.0))
.transact()
.await?;
assert!(alice_succeeds.json::<bool>()? == true);

println!("{:?}", required_deposit);
assert!(res_1.is_success());
// Creating same token fails
let bob_balance = bob_account.view_account().await?.balance;

// Creating token with the required deposit
let res_3 = contract
.call("create_token")
let bob_fails = bob_account
.call(factory.id(), "create_token")
.args_json(json!({"args": token_args}))
.max_gas()
.deposit(NearToken::from_yoctonear(required_deposit.0))
.transact()
.await?;

println!("{:?}", required_deposit);
assert!(res_3.is_failure());
let bob_balance_after = bob_account.view_account().await?.balance;
let rest = bob_balance.saturating_sub(bob_balance_after).as_millinear();
println!("{:?}", rest);

// bob fails
assert!(bob_fails.json::<bool>()? == false);

// but it gets back the money (i.e. looses less than 0.005 N)
assert!(rest < 5);

// Checking created token account and metadata
let token_account_id: AccountId = format!("{}.{}", token_id, contract.id()).parse().unwrap();
let token_account_id: AccountId = format!("{}.{}", token_id, factory.id()).parse().unwrap();
let token_metadata: FungibleTokenMetadata = token_owner_account
.view(&token_account_id, "ft_metadata")
.args_json(json!({}))
Expand Down

0 comments on commit db79ee0

Please sign in to comment.