Skip to content
Closed
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
40 changes: 40 additions & 0 deletions contracts/tholos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ pub struct PauseUpdated {
pub paused: bool,
}

#[contractevent]
pub struct BondAmountUpdated {
pub old_bond_amount: i128,
pub new_bond_amount: i128,
}

#[contractevent]
pub struct RotationProposed {
pub old_resolver: Address,
Expand Down Expand Up @@ -565,6 +571,40 @@ impl Tholos {
Ok(())
}

/// Updates the bond amount required for new assertions. Only callable by
/// the admin set at initialization. Existing in-flight assertions retain
/// the bond amount they were created with; the new amount applies to
/// assertions created after this call.
pub fn set_bond_amount(env: Env, new_bond_amount: i128) -> Result<(), Error> {
let admin: Address = env
.storage()
.instance()
.get(&DataKey::Admin)
.ok_or(Error::NotInitialized)?;
admin.require_auth();
Self::touch_instance_ttl(&env);

if new_bond_amount <= 0 || new_bond_amount > MAX_BOND_AMOUNT {
return Err(Error::InvalidBondAmount);
}

let old_bond_amount: i128 = env
.storage()
.instance()
.get(&DataKey::BondAmount)
.ok_or(Error::NotInitialized)?;
env.storage()
.instance()
.set(&DataKey::BondAmount, &new_bond_amount);
BondAmountUpdated {
old_bond_amount,
new_bond_amount,
}
.publish(&env);

Ok(())
}

fn require_not_paused(env: &Env) -> Result<(), Error> {
let paused: bool = env
.storage()
Expand Down
56 changes: 56 additions & 0 deletions contracts/tholos/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2082,3 +2082,59 @@ mod proptest_initialize_bounds {
}
}
}

#[test]
fn test_set_bond_amount_updates_storage_and_emits_event() {
let fixture = Fixture::new();
let new_bond = DEFAULT_BOND + 50;

fixture.client.set_bond_amount(&new_bond);

let stored: i128 = fixture
.env
.as_contract(&fixture.client.address, || {
fixture.env.storage().instance().get(&DataKey::BondAmount).unwrap()
});
assert_eq!(stored, new_bond);
}

#[test]
fn test_set_bond_amount_rejects_zero() {
let fixture = Fixture::new();
let result = fixture.client.try_set_bond_amount(&0);
assert_eq!(result, Err(Ok(Error::InvalidBondAmount)));
}

#[test]
fn test_set_bond_amount_rejects_negative() {
let fixture = Fixture::new();
let result = fixture.client.try_set_bond_amount(&-1);
assert_eq!(result, Err(Ok(Error::InvalidBondAmount)));
}

#[test]
fn test_set_bond_amount_rejects_above_max() {
let fixture = Fixture::new();
let result = fixture.client.try_set_bond_amount(&(MAX_BOND_AMOUNT + 1));
assert_eq!(result, Err(Ok(Error::InvalidBondAmount)));
}

#[test]
fn test_set_bond_amount_rejects_non_admin() {
let fixture = Fixture::new();
let _attacker = Address::generate(&fixture.env);
fixture.env.set_auths(&[]);
let result = fixture.client.try_set_bond_amount(&(DEFAULT_BOND + 1));
assert!(result.is_err());
}

#[test]
fn test_set_bond_amount_rejects_when_uninitialized() {
let env = Env::default();
env.mock_all_auths();
let contract_id = env.register(Tholos, ());
let client = TholosClient::new(&env, &contract_id);

let result = client.try_set_bond_amount(&(DEFAULT_BOND + 1));
assert_eq!(result, Err(Ok(Error::NotInitialized)));
}
Loading