Skip to content

Commit d45988f

Browse files
committed
feat: add precision loss protection on L2
1 parent f79c165 commit d45988f

File tree

6 files changed

+503
-65
lines changed

6 files changed

+503
-65
lines changed

packages/fungible-token/bridge-fungible-token/src/errors.sw

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ pub enum BridgeFungibleTokenError {
88
OverflowError: (),
99
UnderflowError: (),
1010
AssetNotFound: (),
11+
InvalidAmount: (),
1112
}

packages/fungible-token/bridge-fungible-token/src/interface/bridge.sw

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,5 @@ abi Bridge {
3737
fn asset_to_l1_address(asset_id: AssetId) -> b256;
3838

3939
#[storage(read)]
40-
fn asset_to_l1_decimals(asset_id: AssetId) -> Option<u8>;
40+
fn asset_to_l1_decimals(asset_id: AssetId) -> u8;
4141
}

packages/fungible-token/bridge-fungible-token/src/main.sw

+17-8
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,23 @@ impl Bridge for Contract {
124124
#[payable]
125125
#[storage(read, write)]
126126
fn withdraw(to: b256) {
127-
let amount = msg_amount();
127+
let amount: u64 = msg_amount();
128+
require(amount != 0, BridgeFungibleTokenError::NoCoinsSent);
129+
128130
let asset_id = msg_asset_id();
129131
let sub_id = _asset_to_sub_id(asset_id);
130132
let token_id = _asset_to_token_id(asset_id);
131-
require(amount != 0, BridgeFungibleTokenError::NoCoinsSent);
133+
let l1_address = _asset_to_l1_address(asset_id);
134+
let l1_decimals = storage.l1_decimals.get(l1_address).read();
135+
let l2_decimals = DECIMALS.try_as_u8().unwrap_or(DEFAULT_DECIMALS);
136+
137+
// This prevents loss due to precision when downscaling decimals in L1
138+
if l1_decimals < l2_decimals {
139+
require(
140+
amount % (10u64 ** (l2_decimals - l1_decimals).as_u32()) == 0,
141+
BridgeFungibleTokenError::InvalidAmount
142+
);
143+
}
132144

133145
storage
134146
.tokens_minted
@@ -148,10 +160,7 @@ impl Bridge for Contract {
148160
encode_data(
149161
to,
150162
amount.as_u256().as_b256(),
151-
storage
152-
.l1_addresses
153-
.get(asset_id)
154-
.read(),
163+
l1_address,
155164
token_id,
156165
),
157166
0,
@@ -178,9 +187,9 @@ impl Bridge for Contract {
178187
}
179188

180189
#[storage(read)]
181-
fn asset_to_l1_decimals(asset_id: AssetId) -> Option<u8> {
190+
fn asset_to_l1_decimals(asset_id: AssetId) -> u8 {
182191
let l1_address = _asset_to_l1_address(asset_id);
183-
storage.l1_decimals.get(l1_address).try_read()
192+
storage.l1_decimals.get(l1_address).read()
184193
}
185194

186195
}

0 commit comments

Comments
 (0)