11use defuse:: core:: payload:: multi:: MultiPayload ;
22use defuse:: intents:: ext_intents;
33use defuse_nep245:: { TokenId , receiver:: MultiTokenReceiver } ;
4- use near_sdk:: { AccountId , PromiseOrValue , env, json_types:: U128 , near, serde_json} ;
4+ use near_sdk:: {
5+ AccountId , Gas , GasWeight , NearToken , Promise , PromiseOrValue , env, json_types:: U128 , near,
6+ serde_json,
7+ } ;
8+
9+ // Raw extern function to generate and return bytes of specified length
10+ // Input: 8-byte little-endian u64 specifying the length
11+ #[ cfg( target_arch = "wasm32" ) ]
12+ #[ unsafe( no_mangle) ]
13+ pub extern "C" fn stub_return_bytes ( ) {
14+ if let Some ( input) = near_sdk:: env:: input ( ) {
15+ if input. len ( ) >= 8 {
16+ let len = u64:: from_le_bytes ( input[ ..8 ] . try_into ( ) . unwrap ( ) ) as usize ;
17+ let bytes = vec ! [ 0xf0u8 ; len] ;
18+ near_sdk:: env:: value_return ( & bytes) ;
19+ }
20+ }
21+ }
22+
23+ trait ReturnValueExt : Sized {
24+ fn stub_return_bytes ( self , len : u64 ) -> Self ;
25+ }
26+
27+ impl ReturnValueExt for Promise {
28+ fn stub_return_bytes ( self , len : u64 ) -> Self {
29+ self . function_call_weight (
30+ "stub_return_bytes" ,
31+ len. to_le_bytes ( ) . to_vec ( ) ,
32+ NearToken :: ZERO ,
33+ Gas :: from_ggas ( 0 ) ,
34+ GasWeight ( 1 ) ,
35+ )
36+ }
37+ }
538
639/// Minimal stub contract used for integration tests.
740#[ derive( Default ) ]
@@ -14,6 +47,10 @@ pub struct Contract;
1447pub enum MTReceiverMode {
1548 #[ default]
1649 AcceptAll ,
50+ /// Refund all deposited amounts
51+ RefundAll ,
52+ /// Return u128::MAX for each token (malicious refund attempt)
53+ MaliciousRefund ,
1754 ReturnValue ( U128 ) ,
1855 ReturnValues ( Vec < U128 > ) ,
1956 Panic ,
@@ -22,6 +59,8 @@ pub enum MTReceiverMode {
2259 multipayload : MultiPayload ,
2360 refund_amounts : Vec < U128 > ,
2461 } ,
62+ /// Return raw bytes of specified length (for testing large return values)
63+ ReturnBytes ( U128 ) ,
2564}
2665
2766#[ near]
@@ -34,15 +73,19 @@ impl MultiTokenReceiver for Contract {
3473 amounts : Vec < U128 > ,
3574 msg : String ,
3675 ) -> PromiseOrValue < Vec < U128 > > {
37- near_sdk :: env :: log_str ( & format ! (
38- "STUB::mt_on_transfer: sender_id={sender_id}, previous_owner_ids={previous_owner_ids:?}, token_ids={token_ids:?}, amounts={amounts:?}, msg={msg}"
39- ) ) ;
76+ let _ = sender_id ;
77+ let _ = previous_owner_ids;
78+ let _ = token_ids ;
4079 let mode = serde_json:: from_str ( & msg) . unwrap_or_default ( ) ;
4180
4281 match mode {
82+ MTReceiverMode :: AcceptAll => PromiseOrValue :: Value ( vec ! [ U128 ( 0 ) ; amounts. len( ) ] ) ,
83+ MTReceiverMode :: RefundAll => PromiseOrValue :: Value ( amounts) ,
84+ MTReceiverMode :: MaliciousRefund => {
85+ PromiseOrValue :: Value ( vec ! [ U128 ( u128 :: MAX ) ; amounts. len( ) ] )
86+ }
4387 MTReceiverMode :: ReturnValue ( value) => PromiseOrValue :: Value ( vec ! [ value; amounts. len( ) ] ) ,
4488 MTReceiverMode :: ReturnValues ( values) => PromiseOrValue :: Value ( values) ,
45- MTReceiverMode :: AcceptAll => PromiseOrValue :: Value ( vec ! [ U128 ( 0 ) ; amounts. len( ) ] ) ,
4689 MTReceiverMode :: Panic => env:: panic_str ( "MTReceiverMode::Panic" ) ,
4790 // 16 * 250_000 = 4 MB, which is the limit for a contract return value
4891 MTReceiverMode :: LargeReturn => PromiseOrValue :: Value ( vec ! [ U128 ( u128 :: MAX ) ; 250_000 ] ) ,
@@ -53,6 +96,9 @@ impl MultiTokenReceiver for Contract {
5396 . execute_intents ( vec ! [ multipayload] )
5497 . then ( Self :: ext ( env:: current_account_id ( ) ) . return_refunds ( refund_amounts) )
5598 . into ( ) ,
99+ MTReceiverMode :: ReturnBytes ( len) => Promise :: new ( env:: current_account_id ( ) )
100+ . stub_return_bytes ( len. 0 as u64 )
101+ . into ( ) ,
56102 }
57103 }
58104}
0 commit comments