@@ -151,6 +151,9 @@ pub fn soroban_decode_arg(
151151 Type :: Address ( _) | Type :: String => arg. clone ( ) ,
152152
153153 Type :: Int ( 128 ) | Type :: Uint ( 128 ) => decode_i128 ( wrapper_cfg, vartab, arg) ,
154+
155+ Type :: Int ( 256 ) | Type :: Uint ( 256 ) => decode_i256 ( wrapper_cfg, vartab, arg) ,
156+
154157 Type :: Uint ( 32 ) => {
155158 // get payload out of major bits then truncate to 32‑bit
156159 Expression :: Trunc {
@@ -570,6 +573,86 @@ pub fn soroban_encode_arg(
570573 expr : encoded,
571574 }
572575 }
576+ Type :: Int ( 256 ) | Type :: Uint ( 256 ) => {
577+ // For 256-bit integers, we need to split into four 64-bit pieces
578+ // lo_lo: bits 0-63
579+ // lo_hi: bits 64-127
580+ // hi_lo: bits 128-191
581+ // hi_hi: bits 192-255
582+
583+ let is_signed = matches ! ( item. ty( ) , Type :: Int ( 256 ) ) ;
584+
585+ // Extract lo_lo (bits 0-63)
586+ let lo_lo = Expression :: Trunc {
587+ loc : Loc :: Codegen ,
588+ ty : Type :: Int ( 64 ) ,
589+ expr : Box :: new ( item. clone ( ) ) ,
590+ } ;
591+
592+ // Extract lo_hi (bits 64-127)
593+ let lo_hi_shift = Expression :: ShiftRight {
594+ loc : Loc :: Codegen ,
595+ ty : Type :: Int ( 256 ) ,
596+ left : Box :: new ( item. clone ( ) ) ,
597+ right : Box :: new ( Expression :: NumberLiteral {
598+ loc : Loc :: Codegen ,
599+ ty : Type :: Int ( 256 ) ,
600+ value : BigInt :: from ( 64 ) ,
601+ } ) ,
602+ signed : is_signed,
603+ } ;
604+
605+ let lo_hi = Expression :: Trunc {
606+ loc : Loc :: Codegen ,
607+ ty : Type :: Int ( 64 ) ,
608+ expr : Box :: new ( lo_hi_shift) ,
609+ } ;
610+
611+ // Extract hi_lo (bits 128-191)
612+ let hi_lo_shift = Expression :: ShiftRight {
613+ loc : Loc :: Codegen ,
614+ ty : Type :: Int ( 256 ) ,
615+ left : Box :: new ( item. clone ( ) ) ,
616+ right : Box :: new ( Expression :: NumberLiteral {
617+ loc : Loc :: Codegen ,
618+ ty : Type :: Int ( 256 ) ,
619+ value : BigInt :: from ( 128 ) ,
620+ } ) ,
621+ signed : is_signed,
622+ } ;
623+
624+ let hi_lo = Expression :: Trunc {
625+ loc : Loc :: Codegen ,
626+ ty : Type :: Int ( 64 ) ,
627+ expr : Box :: new ( hi_lo_shift) ,
628+ } ;
629+
630+ // Extract hi_hi (bits 192-255)
631+ let hi_hi_shift = Expression :: ShiftRight {
632+ loc : Loc :: Codegen ,
633+ ty : Type :: Int ( 256 ) ,
634+ left : Box :: new ( item. clone ( ) ) ,
635+ right : Box :: new ( Expression :: NumberLiteral {
636+ loc : Loc :: Codegen ,
637+ ty : Type :: Int ( 256 ) ,
638+ value : BigInt :: from ( 192 ) ,
639+ } ) ,
640+ signed : is_signed,
641+ } ;
642+
643+ let hi_hi = Expression :: Trunc {
644+ loc : Loc :: Codegen ,
645+ ty : Type :: Int ( 64 ) ,
646+ expr : Box :: new ( hi_hi_shift) ,
647+ } ;
648+
649+ let encoded = encode_i256 ( cfg, vartab, lo_lo, lo_hi, hi_lo, hi_hi, item. ty ( ) ) ;
650+ Instr :: Set {
651+ loc : item. loc ( ) ,
652+ res : obj,
653+ expr : encoded,
654+ }
655+ }
573656 Type :: Struct ( StructType :: UserDefined ( n) ) => {
574657 let buf = encode_struct ( item. clone ( ) , cfg, vartab, ns, n) ;
575658
@@ -726,6 +809,52 @@ fn encode_i128(
726809 ret
727810}
728811
812+ /// Encodes a 256-bit integer (signed or unsigned) into a Soroban ScVal.
813+ /// This function handles both Int256 and Uint256 types by splitting them into
814+ /// four 64-bit pieces and using the appropriate host functions.
815+ fn encode_i256 (
816+ cfg : & mut ControlFlowGraph ,
817+ vartab : & mut Vartable ,
818+ lo_lo : Expression ,
819+ lo_hi : Expression ,
820+ hi_lo : Expression ,
821+ hi_hi : Expression ,
822+ int256_ty : Type ,
823+ ) -> Expression {
824+ let ret_var = vartab. temp_anonymous ( & lo_lo. ty ( ) ) ;
825+
826+ let ret = Expression :: Variable {
827+ loc : pt:: Loc :: Codegen ,
828+ ty : lo_lo. ty ( ) . clone ( ) ,
829+ var_no : ret_var,
830+ } ;
831+
832+ // For 256-bit integers, we always use the host functions since they can't fit in a 64-bit ScVal
833+ let instr = match int256_ty {
834+ Type :: Int ( 256 ) => Instr :: Call {
835+ res : vec ! [ ret_var] ,
836+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
837+ call : InternalCallTy :: HostFunction {
838+ name : HostFunctions :: ObjFromI256Pieces . name ( ) . to_string ( ) ,
839+ } ,
840+ args : vec ! [ hi_hi, hi_lo, lo_hi, lo_lo] ,
841+ } ,
842+ Type :: Uint ( 256 ) => Instr :: Call {
843+ res : vec ! [ ret_var] ,
844+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
845+ call : InternalCallTy :: HostFunction {
846+ name : HostFunctions :: ObjFromU256Pieces . name ( ) . to_string ( ) ,
847+ } ,
848+ args : vec ! [ hi_hi, hi_lo, lo_hi, lo_lo] ,
849+ } ,
850+ _ => unreachable ! ( ) ,
851+ } ;
852+
853+ cfg. add ( vartab, instr) ;
854+
855+ ret
856+ }
857+
729858fn decode_i128 ( cfg : & mut ControlFlowGraph , vartab : & mut Vartable , arg : Expression ) -> Expression {
730859 let ty = if let Type :: Ref ( inner_ty) = arg. ty ( ) {
731860 * inner_ty. clone ( )
@@ -922,6 +1051,248 @@ fn decode_i128(cfg: &mut ControlFlowGraph, vartab: &mut Vartable, arg: Expressio
9221051 ret
9231052}
9241053
1054+ /// Decodes a 256-bit integer (signed or unsigned) from a Soroban ScVal.
1055+ /// This function handles both Int256 and Uint256 types by retrieving
1056+ /// the four 64-bit pieces from the host object.
1057+ fn decode_i256 ( cfg : & mut ControlFlowGraph , vartab : & mut Vartable , arg : Expression ) -> Expression {
1058+ let ty = if let Type :: Ref ( inner_ty) = arg. ty ( ) {
1059+ * inner_ty. clone ( )
1060+ } else {
1061+ arg. ty ( )
1062+ } ;
1063+
1064+ let ret_var = vartab. temp_anonymous ( & ty) ;
1065+
1066+ let ret = Expression :: Variable {
1067+ loc : pt:: Loc :: Codegen ,
1068+ ty : ty. clone ( ) ,
1069+ var_no : ret_var,
1070+ } ;
1071+
1072+ // For 256-bit integers, we need to extract all four 64-bit pieces
1073+ // lo_lo: bits 0-63
1074+ // lo_hi: bits 64-127
1075+ // hi_lo: bits 128-191
1076+ // hi_hi: bits 192-255
1077+
1078+ // Extract lo_lo (bits 0-63)
1079+ let lo_lo_var_no = vartab. temp_anonymous ( & Type :: Uint ( 64 ) ) ;
1080+ let lo_lo_var = Expression :: Variable {
1081+ loc : pt:: Loc :: Codegen ,
1082+ ty : Type :: Uint ( 64 ) ,
1083+ var_no : lo_lo_var_no,
1084+ } ;
1085+
1086+ let get_lo_lo_instr = match ty {
1087+ Type :: Int ( 256 ) => Instr :: Call {
1088+ res : vec ! [ lo_lo_var_no] ,
1089+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1090+ call : InternalCallTy :: HostFunction {
1091+ name : HostFunctions :: ObjToI256LoLo . name ( ) . to_string ( ) ,
1092+ } ,
1093+ args : vec ! [ arg. clone( ) ] ,
1094+ } ,
1095+ Type :: Uint ( 256 ) => Instr :: Call {
1096+ res : vec ! [ lo_lo_var_no] ,
1097+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1098+ call : InternalCallTy :: HostFunction {
1099+ name : HostFunctions :: ObjToU256LoLo . name ( ) . to_string ( ) ,
1100+ } ,
1101+ args : vec ! [ arg. clone( ) ] ,
1102+ } ,
1103+ _ => unreachable ! ( ) ,
1104+ } ;
1105+
1106+ cfg. add ( vartab, get_lo_lo_instr) ;
1107+
1108+ // Extract lo_hi (bits 64-127)
1109+ let lo_hi_var_no = vartab. temp_anonymous ( & Type :: Uint ( 64 ) ) ;
1110+ let lo_hi_var = Expression :: Variable {
1111+ loc : pt:: Loc :: Codegen ,
1112+ ty : Type :: Uint ( 64 ) ,
1113+ var_no : lo_hi_var_no,
1114+ } ;
1115+
1116+ let get_lo_hi_instr = match ty {
1117+ Type :: Int ( 256 ) => Instr :: Call {
1118+ res : vec ! [ lo_hi_var_no] ,
1119+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1120+ call : InternalCallTy :: HostFunction {
1121+ name : HostFunctions :: ObjToI256LoHi . name ( ) . to_string ( ) ,
1122+ } ,
1123+ args : vec ! [ arg. clone( ) ] ,
1124+ } ,
1125+ Type :: Uint ( 256 ) => Instr :: Call {
1126+ res : vec ! [ lo_hi_var_no] ,
1127+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1128+ call : InternalCallTy :: HostFunction {
1129+ name : HostFunctions :: ObjToU256LoHi . name ( ) . to_string ( ) ,
1130+ } ,
1131+ args : vec ! [ arg. clone( ) ] ,
1132+ } ,
1133+ _ => unreachable ! ( ) ,
1134+ } ;
1135+
1136+ cfg. add ( vartab, get_lo_hi_instr) ;
1137+
1138+ // Extract hi_lo (bits 128-191)
1139+ let hi_lo_var_no = vartab. temp_anonymous ( & Type :: Uint ( 64 ) ) ;
1140+ let hi_lo_var = Expression :: Variable {
1141+ loc : pt:: Loc :: Codegen ,
1142+ ty : Type :: Uint ( 64 ) ,
1143+ var_no : hi_lo_var_no,
1144+ } ;
1145+
1146+ let get_hi_lo_instr = match ty {
1147+ Type :: Int ( 256 ) => Instr :: Call {
1148+ res : vec ! [ hi_lo_var_no] ,
1149+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1150+ call : InternalCallTy :: HostFunction {
1151+ name : HostFunctions :: ObjToI256HiLo . name ( ) . to_string ( ) ,
1152+ } ,
1153+ args : vec ! [ arg. clone( ) ] ,
1154+ } ,
1155+ Type :: Uint ( 256 ) => Instr :: Call {
1156+ res : vec ! [ hi_lo_var_no] ,
1157+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1158+ call : InternalCallTy :: HostFunction {
1159+ name : HostFunctions :: ObjToU256HiLo . name ( ) . to_string ( ) ,
1160+ } ,
1161+ args : vec ! [ arg. clone( ) ] ,
1162+ } ,
1163+ _ => unreachable ! ( ) ,
1164+ } ;
1165+
1166+ cfg. add ( vartab, get_hi_lo_instr) ;
1167+
1168+ // Extract hi_hi (bits 192-255)
1169+ let hi_hi_var_no = vartab. temp_anonymous ( & Type :: Uint ( 64 ) ) ;
1170+ let hi_hi_var = Expression :: Variable {
1171+ loc : pt:: Loc :: Codegen ,
1172+ ty : Type :: Uint ( 64 ) ,
1173+ var_no : hi_hi_var_no,
1174+ } ;
1175+
1176+ let get_hi_hi_instr = match ty {
1177+ Type :: Int ( 256 ) => Instr :: Call {
1178+ res : vec ! [ hi_hi_var_no] ,
1179+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1180+ call : InternalCallTy :: HostFunction {
1181+ name : HostFunctions :: ObjToI256HiHi . name ( ) . to_string ( ) ,
1182+ } ,
1183+ args : vec ! [ arg. clone( ) ] ,
1184+ } ,
1185+ Type :: Uint ( 256 ) => Instr :: Call {
1186+ res : vec ! [ hi_hi_var_no] ,
1187+ return_tys : vec ! [ Type :: Uint ( 64 ) ] ,
1188+ call : InternalCallTy :: HostFunction {
1189+ name : HostFunctions :: ObjToU256HiHi . name ( ) . to_string ( ) ,
1190+ } ,
1191+ args : vec ! [ arg. clone( ) ] ,
1192+ } ,
1193+ _ => unreachable ! ( ) ,
1194+ } ;
1195+
1196+ cfg. add ( vartab, get_hi_hi_instr) ;
1197+
1198+ // Now combine all pieces to form the 256-bit value
1199+ // Start with hi_hi (bits 192-255)
1200+ let mut combined = Expression :: ZeroExt {
1201+ loc : Loc :: Codegen ,
1202+ ty : ty. clone ( ) ,
1203+ expr : Box :: new ( hi_hi_var) ,
1204+ } ;
1205+
1206+ // Shift left by 64 and add hi_lo (bits 128-191)
1207+ combined = Expression :: ShiftLeft {
1208+ loc : Loc :: Codegen ,
1209+ ty : ty. clone ( ) ,
1210+ left : Box :: new ( combined) ,
1211+ right : Box :: new ( Expression :: NumberLiteral {
1212+ loc : Loc :: Codegen ,
1213+ ty : ty. clone ( ) ,
1214+ value : BigInt :: from ( 64 ) ,
1215+ } ) ,
1216+ } ;
1217+
1218+ let hi_lo_extended = Expression :: ZeroExt {
1219+ loc : Loc :: Codegen ,
1220+ ty : ty. clone ( ) ,
1221+ expr : Box :: new ( hi_lo_var) ,
1222+ } ;
1223+
1224+ combined = Expression :: Add {
1225+ loc : Loc :: Codegen ,
1226+ ty : ty. clone ( ) ,
1227+ overflowing : false ,
1228+ left : Box :: new ( combined) ,
1229+ right : Box :: new ( hi_lo_extended) ,
1230+ } ;
1231+
1232+ // Shift left by 64 and add lo_hi (bits 64-127)
1233+ combined = Expression :: ShiftLeft {
1234+ loc : Loc :: Codegen ,
1235+ ty : ty. clone ( ) ,
1236+ left : Box :: new ( combined) ,
1237+ right : Box :: new ( Expression :: NumberLiteral {
1238+ loc : Loc :: Codegen ,
1239+ ty : ty. clone ( ) ,
1240+ value : BigInt :: from ( 64 ) ,
1241+ } ) ,
1242+ } ;
1243+
1244+ let lo_hi_extended = Expression :: ZeroExt {
1245+ loc : Loc :: Codegen ,
1246+ ty : ty. clone ( ) ,
1247+ expr : Box :: new ( lo_hi_var) ,
1248+ } ;
1249+
1250+ combined = Expression :: Add {
1251+ loc : Loc :: Codegen ,
1252+ ty : ty. clone ( ) ,
1253+ overflowing : false ,
1254+ left : Box :: new ( combined) ,
1255+ right : Box :: new ( lo_hi_extended) ,
1256+ } ;
1257+
1258+ // Shift left by 64 and add lo_lo (bits 0-63)
1259+ combined = Expression :: ShiftLeft {
1260+ loc : Loc :: Codegen ,
1261+ ty : ty. clone ( ) ,
1262+ left : Box :: new ( combined) ,
1263+ right : Box :: new ( Expression :: NumberLiteral {
1264+ loc : Loc :: Codegen ,
1265+ ty : ty. clone ( ) ,
1266+ value : BigInt :: from ( 64 ) ,
1267+ } ) ,
1268+ } ;
1269+
1270+ let lo_lo_extended = Expression :: ZeroExt {
1271+ loc : Loc :: Codegen ,
1272+ ty : ty. clone ( ) ,
1273+ expr : Box :: new ( lo_lo_var) ,
1274+ } ;
1275+
1276+ combined = Expression :: Add {
1277+ loc : Loc :: Codegen ,
1278+ ty : ty. clone ( ) ,
1279+ overflowing : false ,
1280+ left : Box :: new ( combined) ,
1281+ right : Box :: new ( lo_lo_extended) ,
1282+ } ;
1283+
1284+ // Set the final combined value
1285+ let set_instr = Instr :: Set {
1286+ loc : pt:: Loc :: Codegen ,
1287+ res : ret_var,
1288+ expr : combined,
1289+ } ;
1290+
1291+ cfg. add ( vartab, set_instr) ;
1292+
1293+ ret
1294+ }
1295+
9251296fn extract_tag ( arg : Expression ) -> Expression {
9261297 let bit_mask = Expression :: NumberLiteral {
9271298 loc : pt:: Loc :: Codegen ,
0 commit comments