Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 82 additions & 33 deletions smart-contracts/solana/programs/allways_swap_manager/src/backing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,57 @@ use crate::constants::{
use crate::error::ErrorCode;
use crate::state::{BondAttestation, Config, MinerState};

/// The leg denominated in `collateral_chain` — the amount the collateral is sized against. Validity is
/// "backing ∈ legs": a swap whose legs don't include the backing asset has nothing to size against.
pub fn collateral_leg_amount(
collateral_chain: &str,
/// The backing family a chain settles in. An `sn<N>` alpha shares subtensor's account space, so a TAO
/// penalty pays its holder directly — which is why the (quorum-bound) chain id may be trusted for this.
pub fn family(chain: &str) -> &str {
match chain.strip_prefix("sn") {
Some(n) if !n.is_empty() && n.bytes().all(|b| b.is_ascii_digit()) => BACKING_CHAIN_TAO,
_ => chain,
}
}

/// Whether the backing amount is provable from the leg or declared off-chain.
#[derive(Debug, PartialEq)]
pub enum LegBind {
Exact(u128),
Declared,
}

/// Bind `collateral_amount` to the leg denominated in the backing: exact when that leg IS the backing
/// asset, declared when it merely settles in its family. Validity is "backing ∈ leg families".
pub fn collateral_leg_bind(
backing: &str,
from_chain: &str,
from_amount: u128,
to_chain: &str,
to_amount: u128,
) -> Result<u128> {
if collateral_chain == from_chain {
Ok(from_amount)
} else if collateral_chain == to_chain {
Ok(to_amount)
) -> Result<LegBind> {
// Exact legs first: sn7→tao still gets the free on-chain check on its tao leg.
if backing == from_chain {
Ok(LegBind::Exact(from_amount))
} else if backing == to_chain {
Ok(LegBind::Exact(to_amount))
} else if backing == family(from_chain) || backing == family(to_chain) {
Ok(LegBind::Declared)
} else {
err!(ErrorCode::BackingNotInLegs)
}
}

/// The user's own address on the backing chain — whom a penalty settled there is owed to. Same leg
/// lookup as `collateral_leg_amount`, but total: a timeout is terminal, so a backing that is somehow
/// not a leg (finalize already rejects that) yields no payee rather than an error that wedges it.
/// The user's address on the backing leg (exact leg first, as `collateral_leg_bind`) — whom a penalty
/// settled there is owed to. Total: a timeout is terminal, so no leg yields no payee rather than an error.
pub fn collateral_leg_user_addr(
collateral_chain: &str,
from_chain: &str,
user_from_addr: &str,
to_chain: &str,
user_to_addr: &str,
) -> String {
if collateral_chain == from_chain {
user_from_addr.to_string()
} else if collateral_chain == to_chain {
user_to_addr.to_string()
} else {
String::new()
}
let legs = [(from_chain, user_from_addr), (to_chain, user_to_addr)];
legs.iter()
.find(|(chain, _)| collateral_chain == *chain)
.or_else(|| legs.iter().find(|(chain, _)| collateral_chain == family(chain)))
.map_or_else(String::new, |(_, addr)| addr.to_string())
}

/// Swap-size bounds for a backing, in that asset's own smallest unit (0 max = unbounded).
Expand Down Expand Up @@ -73,7 +89,7 @@ pub fn backing_bit(collateral_chain: &str) -> Result<u8> {
pub fn declarable_bit(collateral_chain: &str, from_chain: &str, to_chain: &str) -> Result<u8> {
let bit = backing_bit(collateral_chain)?;
require!(
collateral_chain == from_chain || collateral_chain == to_chain,
collateral_chain == family(from_chain) || collateral_chain == family(to_chain),
ErrorCode::BackingNotInLegs
);
Ok(bit)
Expand Down Expand Up @@ -219,13 +235,48 @@ mod tests {
}

#[test]
fn leg_lookup_finds_the_backing_leg_on_either_side() {
// btc→sol with SOL backing: the dest leg. sol→btc: the source leg. Same rule, no pair branch.
assert_eq!(collateral_leg_amount("sol", "btc", 7, "sol", 11).unwrap(), 11);
assert_eq!(collateral_leg_amount("sol", "sol", 7, "btc", 11).unwrap(), 7);
// A TAO-backed leg is found by exactly the same lookup — the reason a TAO hub costs no diff.
assert_eq!(collateral_leg_amount("tao", "tao", 7, "btc", 11).unwrap(), 7);
assert_eq!(collateral_leg_amount("tao", "btc", 7, "tao", 11).unwrap(), 11);
fn subnet_ids_belong_to_the_tao_family() {
for chain in ["sn7", "sn74"] {
assert_eq!(family(chain), "tao");
}
for chain in ["sn", "sn7x", "snx", "tao", "sol", "btc"] {
assert_eq!(family(chain), chain);
}
}

#[test]
fn exact_leg_binding_matches_the_legacy_lookup() {
fn legacy_leg_amount(
backing: &str, from: &str, from_amt: u128, to: &str, to_amt: u128,
) -> Result<u128> {
if backing == from {
Ok(from_amt)
} else if backing == to {
Ok(to_amt)
} else {
err!(ErrorCode::BackingNotInLegs)
}
}
let pairs = [
("sol", "sol", "btc"), ("sol", "eth", "sol"),
("tao", "tao", "btc"), ("tao", "eth", "tao"),
("sol", "sol", "tao"), ("tao", "sol", "tao"),
];
for (backing, from, to) in pairs {
let legacy = legacy_leg_amount(backing, from, 7, to, 11).unwrap();
assert_eq!(collateral_leg_bind(backing, from, 7, to, 11).unwrap(), LegBind::Exact(legacy));
}
}

#[test]
fn alpha_leg_binding_is_declared_only_for_tao_backing() {
assert_eq!(collateral_leg_bind("tao", "sn7", 7, "avax", 11).unwrap(), LegBind::Declared);
assert_eq!(collateral_leg_bind("tao", "sn7", 7, "sn74", 11).unwrap(), LegBind::Declared);
assert_eq!(collateral_leg_bind("sol", "sn7", 7, "sol", 11).unwrap(), LegBind::Exact(11));
// An alpha↔tao pair keeps the free on-chain check on its tao leg in BOTH directions.
assert_eq!(collateral_leg_bind("tao", "sn7", 7, "tao", 11).unwrap(), LegBind::Exact(11));
assert_eq!(collateral_leg_bind("tao", "tao", 7, "sn7", 11).unwrap(), LegBind::Exact(7));
assert!(collateral_leg_bind("sol", "sn7", 7, "avax", 11).is_err());
}

#[test]
Expand All @@ -235,6 +286,8 @@ mod tests {
assert_eq!(collateral_leg_user_addr("tao", "tao", "u_src", "btc", "u_dst"), "u_src");
assert_eq!(collateral_leg_user_addr("tao", "btc", "u_src", "tao", "u_dst"), "u_dst");
assert_eq!(collateral_leg_user_addr("sol", "sol", "u_src", "tao", "u_dst"), "u_src");
assert_eq!(collateral_leg_user_addr("tao", "sn7", "u_src", "avax", "u_dst"), "u_src");
assert_eq!(collateral_leg_user_addr("tao", "sn7", "u_src", "tao", "u_dst"), "u_dst");
}

#[test]
Expand All @@ -244,12 +297,6 @@ mod tests {
assert_eq!(collateral_leg_user_addr("tao", "btc", "u_src", "eth", "u_dst"), "");
}

#[test]
fn leg_lookup_refuses_a_backing_that_is_not_a_leg() {
// btc→eth backed by SOL has no SOL amount to size collateral against.
assert!(collateral_leg_amount("sol", "btc", 7, "eth", 11).is_err());
}

#[test]
fn sol_reads_local_collateral_and_tao_reads_the_attestation() {
// "sol" ignores any attestation handed to it; "tao" ignores the local vault entirely.
Expand Down Expand Up @@ -335,6 +382,8 @@ mod tests {
fn a_one_hub_pair_can_only_declare_its_hub() {
// tao↔btc: BTC is not a hub and SOL is not a leg, so "tao" is the only declarable backing.
assert_eq!(declarable_bit("tao", "tao", "btc").unwrap(), BACKING_BIT_TAO);
assert_eq!(declarable_bit("tao", "sn7", "avax").unwrap(), BACKING_BIT_TAO);
assert!(declarable_bit("tao", "btc", "avax").is_err());
assert!(declarable_bit("sol", "tao", "btc").is_err()); // not a leg
assert!(declarable_bit("btc", "tao", "btc").is_err()); // a leg, but not a hub
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ pub const CANCEL_REASON_SOL_RESERVED: u8 = 3;
/// An issuer-enabled ERC-20 transfer fee shaves every honest delivery's log below the pinned
/// amount — a hub-wide no-fault condition, cancelled rather than slashed (V-M2/PAXG).
pub const CANCEL_REASON_ERC20_FEE_ENABLED: u8 = 4;
// 5 is CANCEL_REASON_SPL_FROZEN, owned by the Python mirror (allways/constants.py).
pub const CANCEL_REASON_ALPHA_TRANSFER_DISABLED: u8 = 6;
pub const CANCEL_REASON_OTHER: u8 = 255;

/// Slots the draw's seed slot is pinned ahead of the arming crank. Three leader windows (4 slots
Expand Down Expand Up @@ -412,7 +414,7 @@ pub fn fulfillment_grace_secs(to_chain: &str) -> i64 {
FULFILL_GRACE_BTC_SECS
} else if to_chain.eq_ignore_ascii_case("sol") {
FULFILL_GRACE_SOL_SECS
} else if to_chain.eq_ignore_ascii_case("tao") {
} else if crate::backing::family(to_chain).eq_ignore_ascii_case(BACKING_CHAIN_TAO) {
FULFILL_GRACE_TAO_SECS
} else {
FULFILL_GRACE_DEFAULT_SECS
Expand Down Expand Up @@ -496,6 +498,8 @@ mod tests {
assert_eq!(fulfillment_grace_secs("BTC"), FULFILL_GRACE_BTC_SECS);
assert_eq!(fulfillment_grace_secs("sol"), FULFILL_GRACE_SOL_SECS);
assert_eq!(fulfillment_grace_secs("tao"), FULFILL_GRACE_TAO_SECS);
assert_eq!(fulfillment_grace_secs("sn7"), FULFILL_GRACE_TAO_SECS);
assert_eq!(fulfillment_grace_secs("sn74"), FULFILL_GRACE_TAO_SECS);
// An unknown chain must get a real grace, never 0 (that would reopen paid-and-slashed).
assert_eq!(fulfillment_grace_secs("eth"), FULFILL_GRACE_DEFAULT_SECS);
assert!(FULFILL_GRACE_DEFAULT_SECS > 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anchor_lang::prelude::*;

use crate::backing;
use crate::backing::{self, LegBind};
use solana_keccak_hasher::hashv;

use crate::constants::{
Expand Down Expand Up @@ -151,16 +151,16 @@ pub fn handler(
ErrorCode::AmountAboveMax
);

// Bind `collateral_amount` to the leg denominated in the backing asset — the leg lookup that
// closes the understated-collateral hole for any backing, not just SOL.
let expected = backing::collateral_leg_amount(
match backing::collateral_leg_bind(
backing,
&ctx.accounts.reservation.from_chain,
from_amount,
&ctx.accounts.reservation.to_chain,
to_amount,
)?;
require!(collateral_amount as u128 == expected, ErrorCode::InvalidAmount);
)? {
LegBind::Exact(v) => require!(collateral_amount as u128 == v, ErrorCode::InvalidAmount),
LegBind::Declared => {} // bounded by swap_bounds above; understatement policed off-chain
}

// Entry fuse for a backing that settles elsewhere: the relay must be provably alive (or the purse
// read below is trusting a snapshot nobody is refreshing), and the miner must not still owe a
Expand Down
Loading