Skip to content

Commit 9b0d038

Browse files
committed
Merge branch 'tiago/bridge-pool-zero-fees' (#1892)
* origin/tiago/bridge-pool-zero-fees: Changelog for #1892 Refactor validate_changed_keys in the Bridge pool VP Validate txs moving 0 value to the Bridge pool
2 parents c6f30f6 + a524dfa commit 9b0d038

File tree

2 files changed

+150
-5
lines changed

2 files changed

+150
-5
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Allow Bridge pool transfers to pay zero gas fees
2+
([\#1892](https://github.com/anoma/namada/pull/1892))

shared/src/ledger/native_vp/ethereum_bridge/bridge_pool_vp.rs

Lines changed: 148 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ where
387387
escrow_account: &BRIDGE_POOL_ADDRESS,
388388
expected_debit: expected_gas_debit,
389389
expected_credit: expected_gas_credit,
390+
transferred_amount: &transfer.gas_fee.amount,
390391
_kind: PhantomData,
391392
},
392393
token_check: EscrowDelta {
@@ -395,6 +396,7 @@ where
395396
escrow_account: token_check_escrow_acc,
396397
expected_debit: expected_token_debit,
397398
expected_credit: expected_token_credit,
399+
transferred_amount: &transfer.transfer.amount,
398400
_kind: PhantomData,
399401
},
400402
})
@@ -409,21 +411,72 @@ struct EscrowDelta<'a, KIND> {
409411
escrow_account: &'a Address,
410412
expected_debit: Amount,
411413
expected_credit: Amount,
414+
transferred_amount: &'a Amount,
412415
_kind: PhantomData<*const KIND>,
413416
}
414417

415418
impl<KIND> EscrowDelta<'_, KIND> {
416-
fn validate_changed_keys(&self, changed_keys: &BTreeSet<Key>) -> bool {
419+
/// Validate an [`EscrowDelta`].
420+
///
421+
/// # Conditions for validation
422+
///
423+
/// If the transferred amount in the [`EscrowDelta`] is nil,
424+
/// then no keys could have been changed. If the transferred
425+
/// amount is greater than zero, then the appropriate escrow
426+
/// keys must have been written to by some wasm tx.
427+
#[inline]
428+
fn validate(&self, changed_keys: &BTreeSet<Key>) -> bool {
429+
if hints::unlikely(self.transferred_amount_is_nil()) {
430+
self.check_escrow_keys_unchanged(changed_keys)
431+
} else {
432+
self.check_escrow_keys_changed(changed_keys)
433+
}
434+
}
435+
436+
/// Check if all required escrow keys in `changed_keys` were modified.
437+
#[inline]
438+
fn check_escrow_keys_changed(&self, changed_keys: &BTreeSet<Key>) -> bool {
417439
let EscrowDelta {
418440
token,
419441
payer_account,
420442
escrow_account,
421443
..
422444
} = self;
445+
423446
let owner_key = balance_key(token, payer_account);
424447
let escrow_key = balance_key(token, escrow_account);
448+
425449
changed_keys.contains(&owner_key) && changed_keys.contains(&escrow_key)
426450
}
451+
452+
/// Check if no escrow keys in `changed_keys` were modified.
453+
#[inline]
454+
fn check_escrow_keys_unchanged(
455+
&self,
456+
changed_keys: &BTreeSet<Key>,
457+
) -> bool {
458+
let EscrowDelta {
459+
token,
460+
payer_account,
461+
escrow_account,
462+
..
463+
} = self;
464+
465+
let owner_key = balance_key(token, payer_account);
466+
let escrow_key = balance_key(token, escrow_account);
467+
468+
!changed_keys.contains(&owner_key)
469+
&& !changed_keys.contains(&escrow_key)
470+
}
471+
472+
/// Check if the amount transferred to escrow is nil.
473+
#[inline]
474+
fn transferred_amount_is_nil(&self) -> bool {
475+
let EscrowDelta {
476+
transferred_amount, ..
477+
} = self;
478+
transferred_amount.is_zero()
479+
}
427480
}
428481

429482
/// There are two checks we must do when minting wNam.
@@ -437,9 +490,9 @@ struct EscrowCheck<'a> {
437490

438491
impl EscrowCheck<'_> {
439492
#[inline]
440-
fn validate_changed_keys(&self, changed_keys: &BTreeSet<Key>) -> bool {
441-
self.gas_check.validate_changed_keys(changed_keys)
442-
&& self.token_check.validate_changed_keys(changed_keys)
493+
fn validate(&self, changed_keys: &BTreeSet<Key>) -> bool {
494+
self.gas_check.validate(changed_keys)
495+
&& self.token_check.validate(changed_keys)
443496
}
444497
}
445498

@@ -541,7 +594,7 @@ where
541594
let wnam_address = read_native_erc20_address(&self.ctx.pre())?;
542595
let escrow_checks =
543596
self.determine_escrow_checks(&wnam_address, &transfer)?;
544-
if !escrow_checks.validate_changed_keys(keys_changed) {
597+
if !escrow_checks.validate(keys_changed) {
545598
tracing::debug!(
546599
?transfer,
547600
"Missing storage modifications in the Bridge pool"
@@ -1845,4 +1898,94 @@ mod test_bridge_pool_vp {
18451898
Expect::True,
18461899
);
18471900
}
1901+
1902+
/// Test that the Bridge pool native VP validates transfers that
1903+
/// do not contain gas fees and no associated changed keys.
1904+
#[test]
1905+
fn test_no_gas_fees_with_no_changed_keys() {
1906+
let nam_addr = nam();
1907+
let delta = EscrowDelta {
1908+
token: Cow::Borrowed(&nam_addr),
1909+
payer_account: &bertha_address(),
1910+
escrow_account: &BRIDGE_ADDRESS,
1911+
expected_debit: Amount::zero(),
1912+
expected_credit: Amount::zero(),
1913+
// NOTE: testing 0 amount
1914+
transferred_amount: &Amount::zero(),
1915+
// NOTE: testing gas fees
1916+
_kind: PhantomData::<*const GasCheck>,
1917+
};
1918+
// NOTE: testing no changed keys
1919+
let empty_keys = BTreeSet::new();
1920+
1921+
assert!(delta.validate(&empty_keys));
1922+
}
1923+
1924+
/// Test that the Bridge pool native VP rejects transfers that
1925+
/// do not contain gas fees and has associated changed keys.
1926+
#[test]
1927+
fn test_no_gas_fees_with_changed_keys() {
1928+
let nam_addr = nam();
1929+
let delta = EscrowDelta {
1930+
token: Cow::Borrowed(&nam_addr),
1931+
payer_account: &bertha_address(),
1932+
escrow_account: &BRIDGE_ADDRESS,
1933+
expected_debit: Amount::zero(),
1934+
expected_credit: Amount::zero(),
1935+
// NOTE: testing 0 amount
1936+
transferred_amount: &Amount::zero(),
1937+
// NOTE: testing gas fees
1938+
_kind: PhantomData::<*const GasCheck>,
1939+
};
1940+
let owner_key = balance_key(&nam_addr, &bertha_address());
1941+
// NOTE: testing changed keys
1942+
let some_changed_keys = BTreeSet::from([owner_key]);
1943+
1944+
assert!(!delta.validate(&some_changed_keys));
1945+
}
1946+
1947+
/// Test that the Bridge pool native VP validates transfers
1948+
/// moving no value and with no associated changed keys.
1949+
#[test]
1950+
fn test_no_amount_with_no_changed_keys() {
1951+
let nam_addr = nam();
1952+
let delta = EscrowDelta {
1953+
token: Cow::Borrowed(&nam_addr),
1954+
payer_account: &bertha_address(),
1955+
escrow_account: &BRIDGE_ADDRESS,
1956+
expected_debit: Amount::zero(),
1957+
expected_credit: Amount::zero(),
1958+
// NOTE: testing 0 amount
1959+
transferred_amount: &Amount::zero(),
1960+
// NOTE: testing token transfers
1961+
_kind: PhantomData::<*const TokenCheck>,
1962+
};
1963+
// NOTE: testing no changed keys
1964+
let empty_keys = BTreeSet::new();
1965+
1966+
assert!(delta.validate(&empty_keys));
1967+
}
1968+
1969+
/// Test that the Bridge pool native VP rejects transfers
1970+
/// moving no value and with associated changed keys.
1971+
#[test]
1972+
fn test_no_amount_with_changed_keys() {
1973+
let nam_addr = nam();
1974+
let delta = EscrowDelta {
1975+
token: Cow::Borrowed(&nam_addr),
1976+
payer_account: &bertha_address(),
1977+
escrow_account: &BRIDGE_ADDRESS,
1978+
expected_debit: Amount::zero(),
1979+
expected_credit: Amount::zero(),
1980+
// NOTE: testing 0 amount
1981+
transferred_amount: &Amount::zero(),
1982+
// NOTE: testing token transfers
1983+
_kind: PhantomData::<*const TokenCheck>,
1984+
};
1985+
let owner_key = balance_key(&nam_addr, &bertha_address());
1986+
// NOTE: testing changed keys
1987+
let some_changed_keys = BTreeSet::from([owner_key]);
1988+
1989+
assert!(!delta.validate(&some_changed_keys));
1990+
}
18481991
}

0 commit comments

Comments
 (0)