Repository: sedaprotocol/seda-chain-contracts
Pull request #292: Fix: dr config migration
Author: login: gluax
Created: 2025-05-21T15:51:31Z | Merged: 2025-05-21T17:46:45Z

<!--
    Thank you for submitting the PR! We appreciate you spending the time to work on these changes.

    Please help us understand your motivation by explaining why you decided to make this change.

    Happy contributing!
-->

## Motivation

So migrating doesn't break.

## Explanation of Changes

<!-- Please explain why you made these changes the way you did.  -->

Hard check the version and if it's older than this version we will apply the update.
Add old structures to legacy file.
Fix wasm-opt command for latest rust stable for release ci.

## Testing

<!--
    How do you test these changes?
	What command do you run to test these changes specifically?
-->

Let's test to see if this works before I generate the release.

## Dependency Chain
[chain]: https://github.com/sedaprotocol/seda-chain
[explorer]: https://github.com/sedaprotocol/seda-explorer
[overlay-rs]: https://github.com/sedaprotocol/overlay-rs
[overlay-ts]: https://github.com/sedaprotocol/seda-overlay-ts
[sdk]: https://github.com/sedaprotocol/seda-sdk

Think about the changes(msgs, events, limits, etc.) made in this PR and see if you need to make an issue/pr on the following repos.

- [ ] [chain][chain]
- [ ] [explorer/indexer][explorer]
- [ ] [overlay-ts][overlay-ts]
- [ ] [overlay-rs][overlay-rs]
- [ ] [sdk][sdk]

## Related PRs and Issues

<!--
    Please link to any relevant Issues and PRs.
    Also, please link to any relevant SIPs.
-->

N/A


Diff:
diff --git a/.github/workflows/Basic.yml b/.github/workflows/Basic.yml
index 663b1eee..be0a2627 100644
--- a/.github/workflows/Basic.yml
+++ b/.github/workflows/Basic.yml
@@ -17,9 +17,10 @@ jobs:
         uses: actions/checkout@v4
 
       - name: ☁️ Install stable
-        uses: dtolnay/rust-toolchain@stable
+        uses: dtolnay/rust-toolchain@1.86.0
         with:
           target: wasm32-unknown-unknown
+          components: clippy
 
       - name: ☁️ Install Nextest
         uses: taiki-e/install-action@nextest
diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml
index 8a250c17..efec7910 100644
--- a/.github/workflows/Release.yml
+++ b/.github/workflows/Release.yml
@@ -22,7 +22,7 @@ jobs:
           fetch-depth: 0
 
       - name: ☁️ Install Rust
-        uses: dtolnay/rust-toolchain@stable
+        uses: dtolnay/rust-toolchain@1.86.0
         with:
           toolchain: stable
           target: wasm32-unknown-unknown
diff --git a/Cargo.lock b/Cargo.lock
index 000d0eed..7cc3c058 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "addr2line"
@@ -1502,7 +1502,7 @@ dependencies = [
 
 [[package]]
 name = "seda-common"
-version = "1.0.3"
+version = "1.0.4"
 dependencies = [
  "base64",
  "cosmwasm-schema",
@@ -1521,7 +1521,7 @@ dependencies = [
 
 [[package]]
 name = "seda-contract"
-version = "1.0.3"
+version = "1.0.4"
 dependencies = [
  "cosmwasm-schema",
  "cosmwasm-std",
diff --git a/README.md b/README.md
index 2663c811..959ddc59 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,10 @@ The core contract enables some of the core features of the SEDA protocol. It all
 
 ## Dependencies
 
-Before starting, make sure you have [rustup](https://rustup.rs/) along with a recent `rustc` and `cargo` version installed. Currently, we are testing on 1.70.0+. You need to have the `wasm32-unknown-unknown` target installed as well.
+Before starting, make sure you have [rustup](https://rustup.rs/) along with a recent `rustc` and `cargo` version installed. Currently, we are testing on 1.83.0-1.86.0. You need to have the `wasm32-unknown-unknown` target installed as well.
+
+> [!NOTE]
+> Rust `1.87.0` broke the WASM compilation. It requires bulk memory, but then the wasm can't be decode by the chain.
 
 You can check that via:
 
diff --git a/common/Cargo.toml b/common/Cargo.toml
index f6df0fc0..bbc9c1c8 100644
--- a/common/Cargo.toml
+++ b/common/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "seda-common"
-version = "1.0.3"
+version = "1.0.4"
 edition = "2021"
 
 [features]
diff --git a/common/src/msgs/data_requests/execute/mod.rs b/common/src/msgs/data_requests/execute/mod.rs
index e4a11456..c6a77753 100644
--- a/common/src/msgs/data_requests/execute/mod.rs
+++ b/common/src/msgs/data_requests/execute/mod.rs
@@ -11,7 +11,7 @@ pub enum ExecuteMsg {
     CommitDataResult(commit_result::Execute),
     PostDataRequest(post_request::Execute),
     RevealDataResult(reveal_result::Execute),
-    SetTimeoutConfig(DrConfig),
+    SetDrConfig(DrConfig),
 }
 
 impl From<ExecuteMsg> for crate::msgs::ExecuteMsg {
diff --git a/common/src/msgs/data_requests/query.rs b/common/src/msgs/data_requests/query.rs
index 8a51eda8..52254419 100644
--- a/common/src/msgs/data_requests/query.rs
+++ b/common/src/msgs/data_requests/query.rs
@@ -31,6 +31,8 @@ pub enum QueryMsg {
         last_seen_index: Option<(U128, u64, Hash)>,
         limit:           u32,
     },
+    #[cfg_attr(feature = "cosmwasm", returns(DrConfig))]
+    GetDrConfig {},
 }
 
 impl From<QueryMsg> for crate::msgs::QueryMsg {
diff --git a/common/src/msgs/data_requests/types.rs b/common/src/msgs/data_requests/types.rs
index a67362a7..991f8d22 100644
--- a/common/src/msgs/data_requests/types.rs
+++ b/common/src/msgs/data_requests/types.rs
@@ -219,7 +219,7 @@ pub struct DrConfig {
 
 impl From<DrConfig> for crate::msgs::ExecuteMsg {
     fn from(config: DrConfig) -> Self {
-        super::execute::ExecuteMsg::SetTimeoutConfig(config).into()
+        super::execute::ExecuteMsg::SetDrConfig(config).into()
     }
 }
 
diff --git a/contract/Cargo.toml b/contract/Cargo.toml
index 27864d0b..8b2ff39e 100644
--- a/contract/Cargo.toml
+++ b/contract/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "seda-contract"
-version = "1.0.3"
+version = "1.0.4"
 edition.workspace = true
 rust-version.workspace = true
 
diff --git a/contract/src/contract.rs b/contract/src/contract.rs
index 921692c9..b7907a6d 100644
--- a/contract/src/contract.rs
+++ b/contract/src/contract.rs
@@ -10,6 +10,7 @@ use staking::StakingConfig;
 use crate::{
     consts::*,
     error::ContractError,
+    legacy::{TimeoutConfig, TIMEOUT_CONFIG},
     msgs::{
         data_requests::{execute::dr_events::create_dr_config_event, state::DR_CONFIG},
         owner::state::{OWNER, PENDING_OWNER},
@@ -41,6 +42,7 @@ pub fn instantiate(
     #[cfg(test)]
     {
         let version = std::env::var("TEST_CONTRACT_VERSION").unwrap_or_else(|_| "1.0.0".to_string());
+
         set_contract_version(deps.storage, CONTRACT_NAME, &version)?;
     }
     TOKEN.save(deps.storage, &msg.token)?;
@@ -120,29 +122,49 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, Contra
     let version: Version = CONTRACT_VERSION.parse()?;
     let storage_version: Version = get_contract_version(deps.storage)?.version.parse()?;
 
-    let mut response = Response::new().add_attribute("method", "migrate");
-
-    match storage_version.cmp(&version) {
-        std::cmp::Ordering::Greater => {
-            return Err(ContractError::DowngradeNotSupported);
-        }
-        std::cmp::Ordering::Equal => {
-            return Err(ContractError::NoMigrationNeeded);
-        }
-        std::cmp::Ordering::Less => {
-            set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
-
-            response = response.add_event(Event::new("seda-contract").add_attributes([
-                ("action", "migrate".to_string()),
-                ("current_version", storage_version.to_string()),
-                ("target_version", version.to_string()),
-                ("chain_id", CHAIN_ID.load(deps.storage)?.to_string()),
-                ("git_revision", GIT_REVISION.to_string()),
-            ]));
-        }
+    if storage_version > version {
+        return Err(ContractError::DowngradeNotSupported);
+    }
+
+    if storage_version == version {
+        return Err(ContractError::NoMigrationNeeded);
+    }
+
+    const V_1_0_4: Version = Version::new(1, 0, 4);
+    // Migrate timeout_config → dr_config when upgrading from prior to 1.0.4
+    if storage_version < V_1_0_4 {
+        #[cfg(test)]
+        TIMEOUT_CONFIG
+            .save(
+                deps.storage,
+                &TimeoutConfig {
+                    commit_timeout_in_blocks: INITIAL_COMMIT_TIMEOUT_IN_BLOCKS,
+                    reveal_timeout_in_blocks: INITIAL_REVEAL_TIMEOUT_IN_BLOCKS,
+                },
+            )
+            .unwrap();
+
+        let old: TimeoutConfig = TIMEOUT_CONFIG.load(deps.storage)?;
+        let new = DrConfig {
+            commit_timeout_in_blocks: old.commit_timeout_in_blocks,
+            reveal_timeout_in_blocks: old.reveal_timeout_in_blocks,
+            backup_delay_in_blocks:   INITIAL_BACKUP_DELAY_IN_BLOCKS,
+        };
+        DR_CONFIG.save(deps.storage, &new)?;
+        TIMEOUT_CONFIG.remove(deps.storage);
     }
 
-    Ok(response)
+    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
+
+    Ok(Response::new()
+        .add_attribute("method", "migrate")
+        .add_event(Event::new("seda-contract").add_attributes([
+            ("action", "migrate".to_string()),
+            ("current_version", storage_version.to_string()),
+            ("target_version", version.to_string()),
+            ("chain_id", CHAIN_ID.load(deps.storage)?.to_string()),
+            ("git_revision", GIT_REVISION.to_string()),
+        ])))
 }
 
 #[cfg(test)]
@@ -213,7 +235,7 @@ mod tests {
 
     #[test]
     fn migrate_ok() {
-        let test_info = TestInfo::init();
+        let test_info = TestInfo::init_with_version(Some("1.0.3"));
 
         let contract = Box::new(
             ContractWrapper::new(execute, instantiate, query)
@@ -234,5 +256,10 @@ mod tests {
                 new_code_id,
             )
             .is_ok());
+
+        let dr_config = test_info.creator().get_dr_config();
+        assert_eq!(dr_config.commit_timeout_in_blocks, INITIAL_COMMIT_TIMEOUT_IN_BLOCKS);
+        assert_eq!(dr_config.reveal_timeout_in_blocks, INITIAL_REVEAL_TIMEOUT_IN_BLOCKS);
+        assert_eq!(dr_config.backup_delay_in_blocks, INITIAL_BACKUP_DELAY_IN_BLOCKS);
     }
 }
diff --git a/contract/src/legacy.rs b/contract/src/legacy.rs
new file mode 100644
index 00000000..398047e2
--- /dev/null
+++ b/contract/src/legacy.rs
@@ -0,0 +1,9 @@
+use cw_storage_plus::Item;
+
+#[cosmwasm_schema::cw_serde]
+pub struct TimeoutConfig {
+    pub commit_timeout_in_blocks: u64,
+    pub reveal_timeout_in_blocks: u64,
+}
+
+pub const TIMEOUT_CONFIG: Item<TimeoutConfig> = Item::new("timeout_config");
diff --git a/contract/src/lib.rs b/contract/src/lib.rs
index f6ac4233..ba5f89ec 100644
--- a/contract/src/lib.rs
+++ b/contract/src/lib.rs
@@ -6,6 +6,8 @@ pub mod state;
 mod types;
 mod utils;
 
+pub mod legacy;
+
 use seda_common::types as common_types;
 
 #[cfg(test)]
diff --git a/contract/src/msgs/data_requests/execute/mod.rs b/contract/src/msgs/data_requests/execute/mod.rs
index 82fe0311..10fbb643 100644
--- a/contract/src/msgs/data_requests/execute/mod.rs
+++ b/contract/src/msgs/data_requests/execute/mod.rs
@@ -15,7 +15,7 @@ pub(in crate::msgs::data_requests) mod set_dr_config;
 impl ExecuteHandler for ExecuteMsg {
     fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
         // setting the timeout config is an owner operation and should not be paused
-        if PAUSED.load(deps.storage)? && !matches!(self, ExecuteMsg::SetTimeoutConfig(_)) {
+        if PAUSED.load(deps.storage)? && !matches!(self, ExecuteMsg::SetDrConfig(_)) {
             return Err(ContractError::ContractPaused(
                 "data request execute messages".to_string(),
             ));
@@ -25,7 +25,7 @@ impl ExecuteHandler for ExecuteMsg {
             ExecuteMsg::CommitDataResult(msg) => msg.execute(deps, env, info),
             ExecuteMsg::PostDataRequest(msg) => msg.execute(deps, env, info),
             ExecuteMsg::RevealDataResult(msg) => msg.execute(deps, env, info),
-            ExecuteMsg::SetTimeoutConfig(msg) => msg.execute(deps, env, info),
+            ExecuteMsg::SetDrConfig(msg) => msg.execute(deps, env, info),
         }
     }
 }
diff --git a/contract/src/msgs/data_requests/query.rs b/contract/src/msgs/data_requests/query.rs
index 39654875..42325997 100644
--- a/contract/src/msgs/data_requests/query.rs
+++ b/contract/src/msgs/data_requests/query.rs
@@ -2,6 +2,7 @@ use execute::commit_result::verify_commit;
 
 use super::{
     msgs::data_requests::{execute::commit_result, query::QueryMsg},
+    state::DR_CONFIG,
     *,
 };
 use crate::{msgs::sorted_set::IndexKey, state::PAUSED};
@@ -71,6 +72,10 @@ impl QueryHandler for QueryMsg {
                 };
                 to_json_binary(&response)?
             }
+            QueryMsg::GetDrConfig {} => {
+                let config = DR_CONFIG.load(deps.storage)?;
+                to_json_binary(&config)?
+            }
         };
 
         Ok(binary)
diff --git a/contract/src/msgs/data_requests/test_helpers.rs b/contract/src/msgs/data_requests/test_helpers.rs
index e98f83d2..bf983729 100644
--- a/contract/src/msgs/data_requests/test_helpers.rs
+++ b/contract/src/msgs/data_requests/test_helpers.rs
@@ -305,7 +305,12 @@ impl TestAccount {
 
     #[track_caller]
     pub fn set_dr_config(&self, dr_config: DrConfig) -> Result<(), ContractError> {
-        let msg = execute::ExecuteMsg::SetTimeoutConfig(dr_config).into();
+        let msg = execute::ExecuteMsg::SetDrConfig(dr_config).into();
         self.test_info.execute(self, &msg)
     }
+
+    #[track_caller]
+    pub fn get_dr_config(&self) -> DrConfig {
+        self.test_info.query(query::QueryMsg::GetDrConfig {}).unwrap()
+    }
 }


Reviews:
user: login: mariocao
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-21T16:51:04Z
user: login: gluax
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T17:04:05Z
user: login: gluax
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T17:35:55Z
user: login: Thomasvdam
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-21T17:45:24Z

Review comments:
diff_hunk: @@ -99,7 +99,7 @@ fn wasm_opt(sh: &Shell) -> Result<()> {
     wasm(sh)?;
     cmd!(
 			sh,
-			"wasm-opt -Os --signext-lowering target/wasm32-unknown-unknown/release/seda_contract.wasm -o target/seda_contract.wasm"
+			"wasm-opt -Os --signext-lowering --enable-bulk-memory target/wasm32-unknown-unknown/release/seda_contract.wasm -o target/seda_contract.wasm"
path: xtask/src/main.rs
user: login: mariocao
body: Just curious: reason for adding this? 
created_at: 2025-05-21T16:51:04Z
author_association: MEMBER
diff_hunk: @@ -99,7 +99,7 @@ fn wasm_opt(sh: &Shell) -> Result<()> {
     wasm(sh)?;
     cmd!(
 			sh,
-			"wasm-opt -Os --signext-lowering target/wasm32-unknown-unknown/release/seda_contract.wasm -o target/seda_contract.wasm"
+			"wasm-opt -Os --signext-lowering --enable-bulk-memory target/wasm32-unknown-unknown/release/seda_contract.wasm -o target/seda_contract.wasm"
path: xtask/src/main.rs
user: login: gluax
body: https://github.com/sedaprotocol/seda-chain-contracts/actions/runs/15164289057/job/42637909631
created_at: 2025-05-21T17:04:04Z
author_association: COLLABORATOR
diff_hunk: @@ -99,7 +99,7 @@ fn wasm_opt(sh: &Shell) -> Result<()> {
     wasm(sh)?;
     cmd!(
 			sh,
-			"wasm-opt -Os --signext-lowering target/wasm32-unknown-unknown/release/seda_contract.wasm -o target/seda_contract.wasm"
+			"wasm-opt -Os --signext-lowering --enable-bulk-memory target/wasm32-unknown-unknown/release/seda_contract.wasm -o target/seda_contract.wasm"
path: xtask/src/main.rs
user: login: gluax
body: Actually we reverted this change and hard pinned our rust version in the CI. As even with that option it was just broken.
created_at: 2025-05-21T17:35:55Z
author_association: COLLABORATOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-21T17:48:25Z
body: ![Code Coverage](https://img.shields.io/badge/Code%20Coverage-96%25-success?style=flat)

Package | Line Rate | Complexity | Health
-------- | --------- | ---------- | ------
common.src.msgs.staking | 100% | 0 | ✔
common.src.msgs.data_requests.sudo | 100% | 0 | ✔
contract.src.msgs.data_requests | 87% | 0 | ✔
contract.src.msgs.data_requests.sudo | 98% | 0 | ✔
contract.src.msgs.staking | 97% | 0 | ✔
contract.src.msgs.owner | 100% | 0 | ✔
contract.src.msgs.data_requests.state | 98% | 0 | ✔
common.src.msgs.owner.execute | 100% | 0 | ✔
contract.src.msgs.staking.execute | 99% | 0 | ✔
common.src.msgs.data_requests.execute | 100% | 0 | ✔
contract.src.msgs.staking.state | 97% | 0 | ✔
contract.src.msgs.owner.execute | 96% | 0 | ✔
common.src.msgs.owner | 100% | 0 | ✔
common.src.types | 59% | 0 | ➖
contract.src.msgs | 92% | 0 | ✔
contract.src.msgs.data_requests.execute | 99% | 0 | ✔
common.src | 100% | 0 | ✔
contract.src | 90% | 0 | ✔
common.src.msgs | 100% | 0 | ✔
common.src.msgs.staking.execute | 100% | 0 | ✔
common.src.msgs.staking.query | 100% | 0 | ✔
common.src.msgs.data_requests | 99% | 0 | ✔
**Summary** | **96%** (4973 / 5168) | **0** | ✔

<!-- Sticky Pull Request Comment -->
author_association: NONE