Skip to content

Commit 4088533

Browse files
authored
feat: migration setup (#114)
## Description <!-- Brief description of changes --> ## Checklist - [x] I have updated the [docs/SPEC.md](https://github.com/babylonlabs-io/rollup-bsn-contracts/blob/main/docs/SPEC.md) file if this change affects the specification - [x] I have updated the schema by running `cargo gen-schema`
1 parent 7f1727a commit 4088533

File tree

13 files changed

+578
-60
lines changed

13 files changed

+578
-60
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
3737

3838
## Unreleased
3939

40+
### Improvements
41+
42+
* [#114](https://github.com/babylonlabs-io/rollup-bsn-contracts/pull/114) feat: migration setup
43+
44+
4045
## v1.0.0-rc.0
4146

4247
_Release candidate. No changes since v0.2.0. This entry is a placeholder and will be updated if changes are made before final release._

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ cosmwasm-std = { version = "2.1.4", default-features = false, features = [
3232
cw-controllers = "2.0.0"
3333
cw-multi-test = { version = "2.0.1", features = [ "staking", "cosmwasm_1_1", "cosmwasm_2_0" ] }
3434
cw-storage-plus = "2.0.0"
35+
cw2 = "2.0.0"
3536
derivative = "2"
3637
digest = "0.10"
3738
eots = { git = "https://github.com/babylonlabs-io/cosmos-bsn-contracts" }

MIGRATION.md

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# Contract Migration Guide
2+
3+
This guide explains how to safely migrate the Rollup BSN Contract to new
4+
versions in production environments.
5+
6+
## Overview
7+
8+
The Rollup BSN Contract supports migration through CosmWasm's built-in migration
9+
mechanism. This allows you to upgrade the contract's logic while preserving its
10+
state and address, which is essential for production deployments where you need
11+
to add new features or fix bugs without disrupting existing functionality.
12+
13+
## How CosmWasm Migration Works
14+
15+
Understanding the migration process is crucial for successful upgrades:
16+
17+
1. **The `migrate` entry point runs on the NEW code** - When you call `babylond
18+
tx wasm migrate`, the blockchain loads the new contract code and executes its
19+
`migrate` function against the existing state of the contract address.
20+
21+
2. **Migration requirements**:
22+
- The new code you are migrating to must export a `migrate` entry point
23+
- If the new code has no `migrate` export, migration fails with: `"Missing
24+
export: migrate"`
25+
- **Only the contract admin can execute migrations** - this is enforced by
26+
the CosmWasm runtime
27+
- The contract must have been instantiated with an admin (using `--admin`
28+
flag)
29+
30+
3. **Migration flow**:
31+
- Store new contract code → get new `code_id`
32+
- Call migrate with contract address + new `code_id`
33+
- New code's `migrate` entry point executes and can transform state
34+
- On success, the contract address now points to the new `code_id`
35+
- Contract address and storage persist, only the code changes
36+
37+
## Migration Message Format
38+
39+
When executing a migration, you provide a `MigrateMsg` with the following
40+
structure:
41+
42+
```json
43+
{}
44+
```
45+
46+
The migration message is empty for non-state-breaking migrations. Version
47+
tracking is handled automatically using the `cw2` library.
48+
49+
## Migration Types
50+
51+
### Non-State-Breaking Migrations
52+
53+
These migrations don't change the storage structure and are handled
54+
automatically:
55+
56+
- **Logic improvements**: Bug fixes, performance optimizations
57+
- **New functionality**: Adding new execute/query handlers that don't modify
58+
existing state
59+
- **Internal changes**: Refactoring that doesn't affect storage layout
60+
61+
**Example**: Adding enhanced validation or new event emissions without changing
62+
stored data structures.
63+
64+
### State-Breaking Migrations
65+
66+
**Currently not supported.** The current migration implementation only handles
67+
non-state-breaking changes. State-breaking migrations that require data
68+
transformation would need additional implementation in the contract's `migrate`
69+
function.
70+
71+
Examples of state-breaking changes that would require future development:
72+
- **Adding fields**: New fields in existing structs
73+
- **Removing fields**: Deprecated fields that need cleanup
74+
- **Type changes**: Converting field types (e.g., `u32` to `u64`)
75+
- **Storage restructuring**: Changing storage keys or data organization
76+
77+
## Step-by-Step Migration Process
78+
79+
### 1. Build and Store New Contract
80+
81+
```bash
82+
# Build the optimized contract
83+
cargo run-script optimize
84+
85+
# Store the new contract code
86+
STORE_JSON=$(babylond tx wasm store artifacts/finality.wasm \
87+
--from <admin_key> \
88+
--chain-id <chain_id> \
89+
--keyring-backend <keyring_backend> \
90+
--gas auto --gas-adjustment 1.3 \
91+
--fees <fee_amount><fee_denom> \
92+
--broadcast-mode sync \
93+
--output json -y)
94+
95+
# Extract transaction hash and wait for inclusion
96+
STORE_TX=$(echo "$STORE_JSON" | jq -r '.txhash')
97+
sleep 10
98+
99+
# Get the new code ID from transaction events
100+
NEW_CODE_ID=$(babylond query tx "$STORE_TX" --output json | \
101+
jq -r '.events[] | select(.type=="store_code") | .attributes[] |
102+
select(.key=="code_id") | .value')
103+
104+
echo "New code ID: $NEW_CODE_ID"
105+
```
106+
107+
### 2. Execute Migration
108+
109+
```bash
110+
# Migrate the existing contract to the new code
111+
babylond tx wasm migrate <contract_address> $NEW_CODE_ID '{}' \
112+
--from <admin_key> \
113+
--chain-id <chain_id> \
114+
--keyring-backend <keyring_backend> \
115+
--gas auto --gas-adjustment 1.3 \
116+
--fees <fee_amount><fee_denom> \
117+
--broadcast-mode sync \
118+
--output json -y
119+
```
120+
121+
### 3. Verify Migration Success
122+
123+
```bash
124+
# Check that the contract now points to the new code ID
125+
babylond query wasm contract <contract_address> --output json | \
126+
jq -r '.contract_info.code_id'
127+
128+
# Verify the contract is still functional
129+
babylond query wasm contract-state smart <contract_address> '{"config":{}}' \
130+
--output json
131+
```
132+
133+
**Expected results**:
134+
- Code ID should match the `NEW_CODE_ID` from step 1
135+
- Contract address remains unchanged
136+
- Contract should respond to queries normally
137+
138+
## Testing
139+
140+
### Unit Tests
141+
142+
The contract includes migration tests:
143+
144+
```bash
145+
# Run migration-specific tests
146+
cargo test test_migrate -p finality
147+
148+
# Run all tests
149+
cargo test -p finality
150+
```
151+
152+
### Integration Testing
153+
154+
For comprehensive testing in production environments:
155+
156+
1. **Test on testnet first**: Always test the complete migration process on
157+
testnet first
158+
2. **Verify functionality**: Ensure all contract functions work correctly after
159+
migration
160+
3. **Check state integrity**: Confirm that all data has been preserved or
161+
properly transformed
162+
163+
## Troubleshooting
164+
165+
### Common Issues
166+
167+
1. **"Missing export: migrate"**
168+
- **Cause**: The NEW code you are migrating to does not export a `migrate`
169+
entry point
170+
- **Solution**: Rebuild and store code that includes a `migrate` entry point,
171+
then retry the migration
172+
173+
2. **Migration transaction succeeds but code ID doesn't change**
174+
- **Cause**: Transaction may not have been included in a block yet
175+
- **Solution**: Wait longer and re-query, or check transaction events for
176+
errors
177+
178+
3. **"Permission denied" or admin errors**
179+
- **Cause**: Wrong account trying to execute migration, or contract has no
180+
admin set
181+
- **Solution**: Ensure the contract admin is signing the migration
182+
transaction. Check the contract admin with: `babylond query wasm contract
183+
<contract_address>` transaction
184+
185+
4. **State corruption after migration**
186+
- **Cause**: Incomplete or incorrect state transformation in migrate function
187+
- **Solution**: Review migration logic, add comprehensive tests
188+
189+
5. **Gas limit exceeded**
190+
- **Cause**: Complex state migrations require more gas
191+
- **Solution**: Increase gas limit or break migration into smaller steps
192+
193+
### Debugging Steps
194+
195+
1. **Check transaction status**:
196+
```bash
197+
babylond query tx <transaction_hash> --output json
198+
```
199+
200+
2. **Verify contract admin**:
201+
```bash
202+
babylond query wasm contract <contract_address> --output json | jq -r '.contract_info.admin'
203+
```
204+
205+
3. **Check migration events**:
206+
```bash
207+
babylond query tx <migration_tx_hash> --output json | jq '.events'
208+
```
209+
210+
4. **Test on testnet first**: Always test migrations on a testnet before mainnet
211+
212+
## Best Practices
213+
214+
1. **Always test first**: Test migrations thoroughly on testnet before mainnet
215+
2. **Backup important data**: Ensure you have backups of critical contract state
216+
3. **Monitor after migration**: Check contract health and functionality
217+
post-migration
218+
4. **Use version tracking**: Include version strings for clear audit trails
219+
5. **Plan for rollbacks**: Have a strategy if migration issues arise
220+
6. **Secure admin keys**: Ensure migration admin keys are properly secured
221+
7. **Document changes**: Keep clear records of all migration steps and changes
222+
223+
## Migration Capabilities
224+
225+
The Rollup BSN Contract currently supports:
226+
227+
- **Non-state-breaking migrations**: Upgrade logic while preserving existing
228+
data structure
229+
- **Version tracking**: Automatic version tracking using `cw2` library for audit trails
230+
- **Admin-only execution**: Secure migration process restricted to contract
231+
admin
232+
233+
**Note**: State-breaking migrations that require data transformation are not
234+
currently implemented and would require additional development.
235+
236+
## Support and Resources
237+
238+
- **CosmWasm documentation**: [Official CosmWasm migration
239+
guide](https://docs.cosmwasm.com/docs/1.0/smart-contracts/migration)
240+
- **Community support**: Join the Babylon community for migration assistance and
241+
best practices
242+
- **Testing**: Always test thoroughly on testnet before production migrations

contracts/finality/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ cosmwasm-schema = { workspace = true }
2929
cosmwasm-std = { workspace = true }
3030
cw-controllers = { workspace = true }
3131
cw-storage-plus = { workspace = true }
32+
cw2 = { workspace = true }
3233
eots = { workspace = true }
3334
hex = { workspace = true }
3435
k256 = { workspace = true }

contracts/finality/schema/finality.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,8 +647,17 @@
647647
"migrate": {
648648
"$schema": "http://json-schema.org/draft-07/schema#",
649649
"title": "MigrateMsg",
650-
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressible in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
650+
"description": "Migration message for contract upgrades. This can be extended in the future to include migration-specific parameters.",
651651
"type": "object",
652+
"properties": {
653+
"version": {
654+
"description": "Optional version string for tracking migration",
655+
"type": [
656+
"string",
657+
"null"
658+
]
659+
}
660+
},
652661
"additionalProperties": false
653662
},
654663
"sudo": null,
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
{
22
"$schema": "http://json-schema.org/draft-07/schema#",
33
"title": "MigrateMsg",
4-
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressible in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
4+
"description": "Migration message for contract upgrades. This can be extended in the future to include migration-specific parameters.",
55
"type": "object",
6+
"properties": {
7+
"version": {
8+
"description": "Optional version string for tracking migration",
9+
"type": [
10+
"string",
11+
"null"
12+
]
13+
}
14+
},
615
"additionalProperties": false
716
}
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use cosmwasm_schema::write_api;
2-
use cosmwasm_std::Empty;
3-
use finality::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
2+
use finality::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
43

54
fn main() {
65
write_api! {
76
instantiate: InstantiateMsg,
87
query: QueryMsg,
9-
migrate: Empty,
8+
migrate: MigrateMsg,
109
execute: ExecuteMsg,
1110
}
1211
}

0 commit comments

Comments
 (0)