Skip to content

Commit db79ee0

Browse files
committed
fix: refund on error
1 parent 356a14c commit db79ee0

File tree

2 files changed

+53
-17
lines changed

2 files changed

+53
-17
lines changed

src/deploy.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata;
2-
use near_sdk::{borsh, env, json_types::U128, near, require, AccountId, NearToken, Promise};
2+
use near_sdk::{borsh, env, json_types::U128, log, near, require, serde_json::json, AccountId, NearToken, Promise, PromiseError};
33

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

@@ -59,6 +59,12 @@ impl Contract {
5959

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

62+
let user = env::predecessor_account_id();
63+
let callback_args = json!({ "user": user, "deposit": attached })
64+
.to_string()
65+
.into_bytes()
66+
.to_vec();
67+
6268
Promise::new(token_account_id.parse().unwrap())
6369
.create_account()
6470
.transfer(attached)
@@ -69,5 +75,28 @@ impl Contract {
6975
NO_DEPOSIT,
7076
TGAS.saturating_mul(50),
7177
)
78+
.then(Promise::new(env::current_account_id()).function_call(
79+
"create_callback".to_string(),
80+
callback_args,
81+
NearToken::from_near(0),
82+
TGAS.saturating_mul(30),
83+
))
84+
}
85+
86+
#[private]
87+
pub fn create_callback(
88+
&self,
89+
user: AccountId,
90+
deposit: NearToken,
91+
#[callback_result] call_result: Result<(), PromiseError>,
92+
) -> bool {
93+
match call_result {
94+
Ok(_) => true,
95+
Err(e) => {
96+
log!("Error creating token: {:?}", e);
97+
Promise::new(user).transfer(deposit);
98+
false
99+
}
100+
}
72101
}
73102
}

tests/sandbox.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
3030
.transact()
3131
.await?
3232
.into_result()?;
33-
33+
3434
let bob_account = root
3535
.create_subaccount("bob")
3636
.initial_balance(NearToken::from_near(5))
@@ -50,7 +50,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5050
}
5151

5252
async fn create_token(
53-
contract: &Contract,
53+
factory: &Contract,
5454
token_owner_account: &Account,
5555
alice_account: &Account,
5656
bob_account: &Account,
@@ -76,48 +76,55 @@ async fn create_token(
7676
};
7777

7878
// Getting required deposit based on provided arguments
79-
let required_deposit: U128 = contract
79+
let required_deposit: U128 = factory
8080
.view("get_required")
8181
.args_json(json!({"args": token_args}))
8282
.await?
8383
.json()?;
8484

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

9595
// Creating token with the required deposit
96-
let res_1 = contract
97-
.call("create_token")
96+
let alice_succeeds = alice_account
97+
.call(factory.id(), "create_token")
9898
.args_json(json!({"args": token_args}))
9999
.max_gas()
100100
.deposit(NearToken::from_yoctonear(required_deposit.0))
101101
.transact()
102102
.await?;
103+
assert!(alice_succeeds.json::<bool>()? == true);
103104

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

107-
// Creating token with the required deposit
108-
let res_3 = contract
109-
.call("create_token")
108+
let bob_fails = bob_account
109+
.call(factory.id(), "create_token")
110110
.args_json(json!({"args": token_args}))
111111
.max_gas()
112112
.deposit(NearToken::from_yoctonear(required_deposit.0))
113113
.transact()
114114
.await?;
115115

116-
println!("{:?}", required_deposit);
117-
assert!(res_3.is_failure());
116+
let bob_balance_after = bob_account.view_account().await?.balance;
117+
let rest = bob_balance.saturating_sub(bob_balance_after).as_millinear();
118+
println!("{:?}", rest);
119+
120+
// bob fails
121+
assert!(bob_fails.json::<bool>()? == false);
122+
123+
// but it gets back the money (i.e. looses less than 0.005 N)
124+
assert!(rest < 5);
118125

119126
// Checking created token account and metadata
120-
let token_account_id: AccountId = format!("{}.{}", token_id, contract.id()).parse().unwrap();
127+
let token_account_id: AccountId = format!("{}.{}", token_id, factory.id()).parse().unwrap();
121128
let token_metadata: FungibleTokenMetadata = token_owner_account
122129
.view(&token_account_id, "ft_metadata")
123130
.args_json(json!({}))

0 commit comments

Comments
 (0)