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
3 changes: 3 additions & 0 deletions contracts/escrow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ use shared::{
events::*,
types::{Amount, EscrowInfo, Hash, Milestone, MilestoneStatus},
};
use shared::upgradeable::*;
initialize_upgrade(&env, governance_address);
use soroban_sdk::{contract, contractimpl, token::TokenClient, Address, BytesN, Env, Vec};

mod storage;
mod validation;


#[cfg(test)]
mod tests;

Expand Down
6 changes: 6 additions & 0 deletions contracts/project-launch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use soroban_sdk::{
contract, contracterror, contractimpl, contracttype, token::TokenClient, Address, Bytes, Env,
};

use shared::upgradeable::*;

use shared::{
constants::{MAX_PROJECT_DURATION, MIN_CONTRIBUTION, MIN_FUNDING_GOAL, MIN_PROJECT_DURATION},
errors::Error,
Expand Down Expand Up @@ -52,6 +54,10 @@ pub struct ProjectLaunch;

#[contractimpl]
impl ProjectLaunch {

pub fn initialize(env: Env, governance: Address, ...) {
initialize_upgrade(&env, governance);

/// Initialize the contract with an admin address
pub fn initialize(env: Env, admin: Address) -> Result<(), Error> {
if env.storage().instance().has(&DataKey::Admin) {
Expand Down
42 changes: 42 additions & 0 deletions contracts/project-launch/src/test_upgrade.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#[cfg(test)]
mod test {
use soroban_sdk::{Env, BytesN};
use crate::*;

#[test]
fn test_upgrade_timelock() {
let env = Env::default();

// mock addresses etc

// 1. propose upgrade
// 2. attempt execute -> should panic
// 3. advance time
// 4. execute -> should succeed
}
}
#[test]
#[should_panic]
fn test_execute_before_timelock() {
// setup
// propose upgrade
// execute immediately -> should panic
}

env.ledger().with_mut(|li| {
li.timestamp += 48 * 60 * 60;
});

#[test]
#[should_panic]
fn test_pause_blocks_function() {
// pause
// try fund
}

#[test]
#[should_panic]
fn test_double_proposal_fails() {
// propose
// propose again -> panic
}
9 changes: 6 additions & 3 deletions contracts/shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ version.workspace = true
edition.workspace = true
license.workspace = true

[lib]
crate-type = ["rlib", "cdylib"]

[dependencies]
soroban-sdk = { workspace = true }
soroban-sdk = { workspace = true, default-features = false, features = ["alloc"] }

[lib]
crate-type = ["rlib"]
[features]
default = []
3 changes: 3 additions & 0 deletions contracts/shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ pub mod errors;
pub mod events;
pub mod types;
pub mod utils;
pub mod upgradeable;

pub use constants::*;
pub use errors::*;
pub use events::*;
pub use types::*;
pub use utils::*;
pub use upgradeable::*;


pub fn calculate_percentage(amount: i128, percentage: u32, total_percentage: u32) -> i128 {
// Calculate using i128 to avoid precision loss
Expand Down
56 changes: 56 additions & 0 deletions contracts/shared/src/upgradeable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
pub fn execute_upgrade(env: &Env) {
let admin: Address = get_admin(env);
admin.require_auth();

// Ensure upgrade exists
if !env.storage().instance().has(&UpgradeKey::PendingWasmHash) {
panic!("No pending upgrade");
}

// Ensure contract is paused
let paused: bool = env.storage()
.instance()
.get(&UpgradeKey::Paused)
.unwrap();

if !paused {
panic!("Contract must be paused before upgrade");
}

let scheduled: u64 = env.storage()
.instance()
.get(&UpgradeKey::UpgradeTimestamp)
.unwrap();

let now = env.ledger().timestamp();

if now < scheduled {
panic!("Upgrade timelock not expired");
}

let wasm_hash: BytesN<32> = env.storage()
.instance()
.get(&UpgradeKey::PendingWasmHash)
.unwrap();

env.deployer().update_current_contract_wasm(wasm_hash);

// Increment version
let version: u32 = env.storage()
.instance()
.get(&UpgradeKey::Version)
.unwrap();

env.storage()
.instance()
.set(&UpgradeKey::Version, &(version + 1));

// Clear proposal
env.storage()
.instance()
.remove(&UpgradeKey::PendingWasmHash);

env.storage()
.instance()
.remove(&UpgradeKey::UpgradeTimestamp);
}