@@ -115,6 +115,8 @@ pub enum Error {
115115 SendingToken ( String ) ,
116116 #[ error( "Receiving a token error: {0}" ) ]
117117 ReceivingToken ( String ) ,
118+ #[ error( "IBC storage error: {0}" ) ]
119+ IbcStorage ( storage:: Error ) ,
118120}
119121
120122// This is needed to use `ibc::Handler::Error` with `IbcActions` in
@@ -161,9 +163,8 @@ pub trait IbcActions {
161163 /// Transfer token
162164 fn transfer_token (
163165 & mut self ,
164- src : & Address ,
165- dest : & Address ,
166- token : & Address ,
166+ src : & Key ,
167+ dest : & Key ,
167168 amount : Amount ,
168169 ) -> std:: result:: Result < ( ) , Self :: Error > ;
169170
@@ -934,51 +935,87 @@ pub trait IbcActions {
934935 & mut self ,
935936 msg : & MsgTransfer ,
936937 ) -> std:: result:: Result < ( ) , Self :: Error > {
937- let data = FungibleTokenPacketData :: from ( msg. clone ( ) ) ;
938- let source = Address :: decode ( data. sender . clone ( ) ) . map_err ( |e| {
939- Error :: SendingToken ( format ! (
940- "Invalid sender address: sender {}, error {}" ,
941- data. sender, e
942- ) )
943- } ) ?;
944- let token_str = data. denom . split ( '/' ) . last ( ) . ok_or_else ( || {
945- Error :: SendingToken ( format ! (
946- "No token was specified: {}" ,
947- data. denom
948- ) )
949- } ) ?;
950- let token = Address :: decode ( token_str) . map_err ( |e| {
951- Error :: SendingToken ( format ! (
952- "Invalid token address: token {}, error {}" ,
953- token_str, e
954- ) )
955- } ) ?;
938+ let mut data = FungibleTokenPacketData :: from ( msg. clone ( ) ) ;
939+ if let Some ( hash) = storage:: token_hash_from_denom ( & data. denom )
940+ . map_err ( Error :: IbcStorage ) ?
941+ {
942+ let denom_key = storage:: ibc_denom_key ( & hash) ;
943+ let denom_bytes =
944+ self . read_ibc_data ( & denom_key) ?. ok_or_else ( || {
945+ Error :: SendingToken ( format ! (
946+ "No original denom: denom_key {}" ,
947+ denom_key
948+ ) )
949+ } ) ?;
950+ let denom = std:: str:: from_utf8 ( & denom_bytes) . map_err ( |e| {
951+ Error :: SendingToken ( format ! (
952+ "Decoding the denom failed: denom_key {}, error {}" ,
953+ denom_key, e
954+ ) )
955+ } ) ?;
956+ data. denom = denom. to_string ( ) ;
957+ }
958+ let token = storage:: token ( & data. denom ) . map_err ( Error :: IbcStorage ) ?;
956959 let amount = Amount :: from_str ( & data. amount ) . map_err ( |e| {
957960 Error :: SendingToken ( format ! (
958961 "Invalid amount: amount {}, error {}" ,
959962 data. amount, e
960963 ) )
961964 } ) ?;
962965
963- // check the denom field
966+ let source_addr = Address :: decode ( & data. sender ) . map_err ( |e| {
967+ Error :: SendingToken ( format ! (
968+ "Invalid sender address: sender {}, error {}" ,
969+ data. sender, e
970+ ) )
971+ } ) ?;
972+
973+ // check the denomination field
964974 let prefix = format ! (
965975 "{}/{}/" ,
966976 msg. source_port. clone( ) ,
967977 msg. source_channel. clone( )
968978 ) ;
969- if data. denom . starts_with ( & prefix) {
970- // sink zone
971- let burn = Address :: Internal ( InternalAddress :: IbcBurn ) ;
972- self . transfer_token ( & source, & burn, & token, amount) ?;
979+ let ( source, target) = if data. denom . starts_with ( & prefix) {
980+ // the receiver's chain was the source
981+ // transfer from the origin-specific account of the token
982+ let key_prefix = storage:: ibc_token_prefix ( & data. denom )
983+ . map_err ( Error :: IbcStorage ) ?;
984+ let src = token:: multitoken_balance_key ( & key_prefix, & source_addr) ;
985+
986+ let key_prefix = storage:: ibc_account_prefix (
987+ & msg. source_port ,
988+ & msg. source_channel ,
989+ & token,
990+ ) ;
991+ let burn = token:: multitoken_balance_key (
992+ & key_prefix,
993+ & Address :: Internal ( InternalAddress :: IbcBurn ) ,
994+ ) ;
995+ ( src, burn)
973996 } else {
974- // source zone
975- let escrow =
976- Address :: Internal ( InternalAddress :: ibc_escrow_address (
977- msg. source_port . to_string ( ) ,
978- msg. source_channel . to_string ( ) ,
979- ) ) ;
980- self . transfer_token ( & source, & escrow, & token, amount) ?;
981- }
997+ // this chain is the source
998+ // escrow the amount of the token
999+ let src = if data. denom == token. to_string ( ) {
1000+ token:: balance_key ( & token, & source_addr)
1001+ } else {
1002+ let key_prefix = storage:: ibc_token_prefix ( & data. denom )
1003+ . map_err ( Error :: IbcStorage ) ?;
1004+ token:: multitoken_balance_key ( & key_prefix, & source_addr)
1005+ } ;
1006+
1007+ let key_prefix = storage:: ibc_account_prefix (
1008+ & msg. source_port ,
1009+ & msg. source_channel ,
1010+ & token,
1011+ ) ;
1012+ let escrow = token:: multitoken_balance_key (
1013+ & key_prefix,
1014+ & Address :: Internal ( InternalAddress :: IbcEscrow ) ,
1015+ ) ;
1016+ ( src, escrow)
1017+ } ;
1018+ self . transfer_token ( & source, & target, amount) ?;
9821019
9831020 // send a packet
9841021 let port_channel_id =
@@ -999,49 +1036,82 @@ pub trait IbcActions {
9991036 packet : & Packet ,
10001037 data : & FungibleTokenPacketData ,
10011038 ) -> std:: result:: Result < ( ) , Self :: Error > {
1002- let dest = Address :: decode ( data. receiver . clone ( ) ) . map_err ( |e| {
1003- Error :: ReceivingToken ( format ! (
1004- "Invalid receiver address: receiver {}, error {}" ,
1005- data. receiver, e
1006- ) )
1007- } ) ?;
1008- let token_str = data. denom . split ( '/' ) . last ( ) . ok_or_else ( || {
1009- Error :: ReceivingToken ( format ! (
1010- "No token was specified: {}" ,
1011- data. denom
1012- ) )
1013- } ) ?;
1014- let token = Address :: decode ( token_str) . map_err ( |e| {
1015- Error :: ReceivingToken ( format ! (
1016- "Invalid token address: token {}, error {}" ,
1017- token_str, e
1018- ) )
1019- } ) ?;
1039+ let token = storage:: token ( & data. denom ) . map_err ( Error :: IbcStorage ) ?;
10201040 let amount = Amount :: from_str ( & data. amount ) . map_err ( |e| {
10211041 Error :: ReceivingToken ( format ! (
10221042 "Invalid amount: amount {}, error {}" ,
10231043 data. amount, e
10241044 ) )
10251045 } ) ?;
1046+ // The receiver should be an address because the origin-specific account
1047+ // key should be assigned internally
1048+ let dest_addr = Address :: decode ( & data. receiver ) . map_err ( |e| {
1049+ Error :: ReceivingToken ( format ! (
1050+ "Invalid receiver address: receiver {}, error {}" ,
1051+ data. receiver, e
1052+ ) )
1053+ } ) ?;
10261054
10271055 let prefix = format ! (
10281056 "{}/{}/" ,
10291057 packet. source_port. clone( ) ,
10301058 packet. source_channel. clone( )
10311059 ) ;
1032- if data. denom . starts_with ( & prefix) {
1033- // unescrow the token because this chain is the source
1034- let escrow =
1035- Address :: Internal ( InternalAddress :: ibc_escrow_address (
1036- packet. destination_port . to_string ( ) ,
1037- packet. destination_channel . to_string ( ) ,
1038- ) ) ;
1039- self . transfer_token ( & escrow, & dest, & token, amount) ?;
1040- } else {
1041- // mint the token because the sender chain is the source
1042- let mint = Address :: Internal ( InternalAddress :: IbcMint ) ;
1043- self . transfer_token ( & mint, & dest, & token, amount) ?;
1044- }
1060+ let ( source, target) = match data. denom . strip_prefix ( & prefix) {
1061+ Some ( denom) => {
1062+ // unescrow the token because this chain was the source
1063+ let escrow_prefix = storage:: ibc_account_prefix (
1064+ & packet. destination_port ,
1065+ & packet. destination_channel ,
1066+ & token,
1067+ ) ;
1068+ let escrow = token:: multitoken_balance_key (
1069+ & escrow_prefix,
1070+ & Address :: Internal ( InternalAddress :: IbcEscrow ) ,
1071+ ) ;
1072+ let dest = if denom == token. to_string ( ) {
1073+ token:: balance_key ( & token, & dest_addr)
1074+ } else {
1075+ let key_prefix = storage:: ibc_token_prefix ( denom)
1076+ . map_err ( Error :: IbcStorage ) ?;
1077+ token:: multitoken_balance_key ( & key_prefix, & dest_addr)
1078+ } ;
1079+ ( escrow, dest)
1080+ }
1081+ None => {
1082+ // mint the token because the sender chain is the source
1083+ let key_prefix = storage:: ibc_account_prefix (
1084+ & packet. destination_port ,
1085+ & packet. destination_channel ,
1086+ & token,
1087+ ) ;
1088+ let mint = token:: multitoken_balance_key (
1089+ & key_prefix,
1090+ & Address :: Internal ( InternalAddress :: IbcMint ) ,
1091+ ) ;
1092+
1093+ // prefix the denom with the this chain port and channel
1094+ let denom = format ! (
1095+ "{}/{}/{}" ,
1096+ & packet. destination_port,
1097+ & packet. destination_channel,
1098+ & data. denom
1099+ ) ;
1100+ let key_prefix = storage:: ibc_token_prefix ( & denom)
1101+ . map_err ( Error :: IbcStorage ) ?;
1102+ let dest =
1103+ token:: multitoken_balance_key ( & key_prefix, & dest_addr) ;
1104+
1105+ // store the prefixed denom
1106+ let token_hash = storage:: calc_hash ( & denom) ;
1107+ let denom_key = storage:: ibc_denom_key ( token_hash) ;
1108+ self . write_ibc_data ( & denom_key, denom. as_bytes ( ) ) ?;
1109+
1110+ ( mint, dest)
1111+ }
1112+ } ;
1113+ self . transfer_token ( & source, & target, amount) ?;
1114+
10451115 Ok ( ( ) )
10461116 }
10471117
@@ -1051,49 +1121,64 @@ pub trait IbcActions {
10511121 packet : & Packet ,
10521122 data : & FungibleTokenPacketData ,
10531123 ) -> std:: result:: Result < ( ) , Self :: Error > {
1054- let dest = Address :: decode ( data. sender . clone ( ) ) . map_err ( |e| {
1055- Error :: ReceivingToken ( format ! (
1056- "Invalid sender address: sender {}, error {}" ,
1057- data. sender, e
1058- ) )
1059- } ) ?;
1060- let token_str = data. denom . split ( '/' ) . last ( ) . ok_or_else ( || {
1061- Error :: ReceivingToken ( format ! (
1062- "No token was specified: {}" ,
1063- data. denom
1064- ) )
1065- } ) ?;
1066- let token = Address :: decode ( token_str) . map_err ( |e| {
1067- Error :: ReceivingToken ( format ! (
1068- "Invalid token address: token {}, error {}" ,
1069- token_str, e
1070- ) )
1071- } ) ?;
1124+ let token = storage:: token ( & data. denom ) . map_err ( Error :: IbcStorage ) ?;
10721125 let amount = Amount :: from_str ( & data. amount ) . map_err ( |e| {
10731126 Error :: ReceivingToken ( format ! (
10741127 "Invalid amount: amount {}, error {}" ,
10751128 data. amount, e
10761129 ) )
10771130 } ) ?;
10781131
1132+ let dest_addr = Address :: decode ( & data. sender ) . map_err ( |e| {
1133+ Error :: SendingToken ( format ! (
1134+ "Invalid sender address: sender {}, error {}" ,
1135+ data. sender, e
1136+ ) )
1137+ } ) ?;
1138+
10791139 let prefix = format ! (
10801140 "{}/{}/" ,
10811141 packet. source_port. clone( ) ,
10821142 packet. source_channel. clone( )
10831143 ) ;
1084- if data. denom . starts_with ( & prefix) {
1085- // mint the token because the sender chain is the sink zone
1086- let mint = Address :: Internal ( InternalAddress :: IbcMint ) ;
1087- self . transfer_token ( & mint, & dest, & token, amount) ?;
1144+ let ( source, target) = if data. denom . starts_with ( & prefix) {
1145+ // mint the token because the amount was burned
1146+ let key_prefix = storage:: ibc_account_prefix (
1147+ & packet. source_port ,
1148+ & packet. source_channel ,
1149+ & token,
1150+ ) ;
1151+ let mint = token:: multitoken_balance_key (
1152+ & key_prefix,
1153+ & Address :: Internal ( InternalAddress :: IbcMint ) ,
1154+ ) ;
1155+ let key_prefix = storage:: ibc_token_prefix ( & data. denom )
1156+ . map_err ( Error :: IbcStorage ) ?;
1157+ let dest = token:: multitoken_balance_key ( & key_prefix, & dest_addr) ;
1158+ ( mint, dest)
10881159 } else {
1089- // unescrow the token because the sender chain is the source zone
1090- let escrow =
1091- Address :: Internal ( InternalAddress :: ibc_escrow_address (
1092- packet. source_port . to_string ( ) ,
1093- packet. source_channel . to_string ( ) ,
1094- ) ) ;
1095- self . transfer_token ( & escrow, & dest, & token, amount) ?;
1096- }
1160+ // unescrow the token because the acount was escrowed
1161+ let dest = if data. denom == token. to_string ( ) {
1162+ token:: balance_key ( & token, & dest_addr)
1163+ } else {
1164+ let key_prefix = storage:: ibc_token_prefix ( & data. denom )
1165+ . map_err ( Error :: IbcStorage ) ?;
1166+ token:: multitoken_balance_key ( & key_prefix, & dest_addr)
1167+ } ;
1168+
1169+ let key_prefix = storage:: ibc_account_prefix (
1170+ & packet. source_port ,
1171+ & packet. source_channel ,
1172+ & token,
1173+ ) ;
1174+ let escrow = token:: multitoken_balance_key (
1175+ & key_prefix,
1176+ & Address :: Internal ( InternalAddress :: IbcEscrow ) ,
1177+ ) ;
1178+ ( escrow, dest)
1179+ } ;
1180+ self . transfer_token ( & source, & target, amount) ?;
1181+
10971182 Ok ( ( ) )
10981183 }
10991184}
0 commit comments