Skip to content

Commit e1dc067

Browse files
committed
contract-sdk/specs/token/oas20: Rollback if subcall fails in send
1 parent 28a2e67 commit e1dc067

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

contract-sdk/specs/token/oas20/src/helpers.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use oasis_contract_sdk::{
22
self as sdk,
33
env::Env,
44
types::{
5-
message::{Message, NotifyReply},
5+
message::{CallResult, Message, NotifyReply, Reply},
66
InstanceId,
77
},
88
};
@@ -14,6 +14,9 @@ use crate::types::{
1414
TokenInstantiation,
1515
};
1616

17+
/// Unique identifier for the send subcall.
18+
pub const CALL_ID_SEND: u64 = 1;
19+
1720
/// Handles an OAS20 request call.
1821
pub fn handle_call<C: sdk::Context>(
1922
ctx: &mut C,
@@ -34,7 +37,16 @@ pub fn handle_call<C: sdk::Context>(
3437
}
3538
Request::Send { to, amount, data } => {
3639
let from = ctx.caller_address().to_owned();
37-
send(ctx, balances, from, to, amount, data, 0, NotifyReply::Never)?;
40+
send(
41+
ctx,
42+
balances,
43+
from,
44+
to,
45+
amount,
46+
data,
47+
CALL_ID_SEND,
48+
NotifyReply::OnError, // Rollback if subcall fails.
49+
)?;
3850

3951
ctx.emit_event(Event::Oas20Sent { from, to, amount });
4052

@@ -120,6 +132,24 @@ pub fn handle_query<C: sdk::Context>(
120132
}
121133
}
122134

135+
/// Handles a reply from OAS20 execution.
136+
pub fn handle_reply<C: sdk::Context>(
137+
_ctx: &mut C,
138+
_token_info: PublicCell<TokenInformation>,
139+
_balances: PublicMap<Address, u128>,
140+
_allowances: PublicMap<(Address, Address), u128>,
141+
reply: Reply,
142+
) -> Result<Option<Response>, Error> {
143+
match reply {
144+
Reply::Call {
145+
id: CALL_ID_SEND,
146+
result: CallResult::Failed { module, code },
147+
..
148+
} => Err(Error::ReceiverCallFailed(module, code)),
149+
_ => Ok(None),
150+
}
151+
}
152+
123153
/// Instantiates the contract state.
124154
pub fn instantiate<C: sdk::Context>(
125155
ctx: &mut C,

contract-sdk/specs/token/oas20/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ extern crate alloc;
44
pub mod helpers;
55
pub mod types;
66

7-
use oasis_contract_sdk::{self as sdk};
7+
use oasis_contract_sdk::{self as sdk, types::message::Reply};
88
use oasis_contract_sdk_storage::{cell::PublicCell, map::PublicMap};
99
use oasis_contract_sdk_types::address::Address;
1010

@@ -50,6 +50,10 @@ impl sdk::Contract for Oas20Token {
5050
fn query<C: sdk::Context>(ctx: &mut C, request: Request) -> Result<Response, Error> {
5151
helpers::handle_query(ctx, TOKEN_INFO, BALANCES, ALLOWANCES, request)
5252
}
53+
54+
fn handle_reply<C: sdk::Context>(ctx: &mut C, reply: Reply) -> Result<Option<Response>, Error> {
55+
helpers::handle_reply(ctx, TOKEN_INFO, BALANCES, ALLOWANCES, reply)
56+
}
5357
}
5458

5559
// Create the required WASM exports required for the contract to be runnable.

contract-sdk/specs/token/oas20/src/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ pub enum Error {
9090
#[error("insufficient allowance")]
9191
#[sdk_error(code = 8)]
9292
InsufficientAllowance,
93+
94+
#[error("receiver call failed (module: {0} code: {1})")]
95+
#[sdk_error(code = 9)]
96+
ReceiverCallFailed(String, u32),
9397
}
9498

9599
/// All possible events that can be returned by the OAS20 contract.

0 commit comments

Comments
 (0)