Skip to content
Open
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
38 changes: 13 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

<div align="center">

![Da Nang Hackcamp](./assets/danang_hackcamp.png)
Expand Down Expand Up @@ -33,7 +32,7 @@ git clone https://github.com/openguild-labs/open-danang-hackcamp-2025.git
Go to **Participant Registration** section and register to be the workshop participants. Add the below to the list, replace any placeholder with your personal information.

```
| 🦄 | Name | Github username | Your current occupation |
| 🦄 | Ben Ha | benhaq | Blockchain Developer |
```

- Step 5: `Commit` your code and push to the forked Github repository
Expand All @@ -53,38 +52,36 @@ git commit -m "<Your Name> | Register for OpenGuild Da Nang Hackcamp 2025"

## Discover the List of Challenges 🏆

Total OpenGuild prize pool: **2000$ / 5 winners**
Total OpenGuild prize pool: **2000$ / 5 winners**
<br/>
Total Bifrost Parner prize pool: **300$-1000$** (dedicated to Bifrost's Challenge)
| Challenge | Description | Action | Bounty |
| Challenge | Description | Action | Bounty |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ------ |
| 1 | Building Uniswap V2 Application | [Take Challenge](./challenge-1-uniswapv2/README.md) | $ |
| 2 | Building Lending and Borrowing Application | [Take Challenge](./challenge-2-lending-borrowing/README.md) | $ |
| 3 | Build a cross-chain application using XCM | [Take Challenge](./challenge-3-xcm/README.md) | $ |
| 4 | Polkadot SDK | [Take Challenge](./challenge-4-polkadot-sdk/README.md) | $ |
| Parner Track - Bifrost | Create a unique and optimal UX for interacting with Bifrost Liquid Staking Tokens available on many chains | [Take Challenge](./challenge-bifrost/README.md) | $300-$1000 |
| 1 | Building Uniswap V2 Application | [Take Challenge](./challenge-1-uniswapv2/README.md) | $ |
| 2 | Building Lending and Borrowing Application | [Take Challenge](./challenge-2-lending-borrowing/README.md) | $ |
| 3 | Build a cross-chain application using XCM | [Take Challenge](./challenge-3-xcm/README.md) | $ |
| 4 | Polkadot SDK | [Take Challenge](./challenge-4-polkadot-sdk/README.md) | $ |
| Parner Track - Bifrost | Create a unique and optimal UX for interacting with Bifrost Liquid Staking Tokens available on many chains | [Take Challenge](./challenge-bifrost/README.md) | $300-$1000 |
</br>
</br>

</div>

## 👉 Resource for Development and Support Channels

### Paseo Contract Faucet
### Paseo Contract Faucet

Link : https://faucet.polkadot.io/?parachain=1111

### Explorer
### Explorer

Link : https://blockscout-passet-hub.parity-testnet.parity.io/

### RPC

+ ETH - EVM-compatible RPC: `https://testnet-passet-hub-eth-rpc.polkadot.io/`

+ ChainID: `0x190f1b45`

- ETH - EVM-compatible RPC: `https://testnet-passet-hub-eth-rpc.polkadot.io/`

- ChainID: `0x190f1b45`

### Resources

Expand All @@ -97,17 +94,13 @@ Link : https://blockscout-passet-hub.parity-testnet.parity.io/
- [OpenGuild Learn](https://learn.openguild.wtf/)

### Support Channels

- [Discord OpenGuild](https://github.com/openguild-labs)
- [Discord Polkadot](https://discord.gg/polkadot)
- [Stack Exchange](https://substrate.meta.stackexchange.com/)
- [Telegram](https://t.me/substratedevs)
- [Reddit](https://www.reddit.com/r/Polkadot/)






## 👉 Contribute to OpenGuild Community

OpenGuild is a builder-driven community centered around Polkadot. OpenGuild is built by Web3 builders for Web3 builders. Our primary aim is to cater to developers seeking a comprehensive understanding of the Polkadot blockchain, providing curated, in-depth materials with a low-level approach.
Expand All @@ -116,8 +109,3 @@ OpenGuild is a builder-driven community centered around Polkadot. OpenGuild is b
- **Website:** [OpenGuild Website](https://openguild.wtf/)
- **Github:** [OpenGuild Labs](https://github.com/openguild-labs)
- **Discord**: [Openguild Discord Channel](https://discord.gg/bcjMzxqtD7)





1 change: 1 addition & 0 deletions challenge-4-polkadot-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ polkadot-sdk = { version = "2503.0.1", default-features = false }
codec = { version = "3.7.4", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.6", default-features = false }
serde_json = { version = "1.0.132", default-features = false }
pallet-balances = { version = "41.1.0", default-features = false }

[profile.release]
opt-level = 3
Expand Down
185 changes: 161 additions & 24 deletions challenge-4-polkadot-sdk/README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,52 @@

## Challenge details

Polkadot SDK provides a framework for building custom blockchains (parachains) with modular runtime pallets. It enables developers to create specialized blockchain solutions with custom functionality.

## Hackers can choose one of the following features:
## Hackers can choose one of the following features:

1. Vesting:

+ Vesting schedule creation
+ Vesting amount calculation
+ Vesting claim processing
+ Vesting schedule updates
- Vesting schedule creation
- Vesting amount calculation
- Vesting claim processing
- Vesting schedule updates

2. Native Pool:

NativePool provides a service where people can deposit native token and they will receive daily rewards. Users must be able to take out their deposits along with their portion of rewards at any time. New rewards are deposited manually into the pool by the NativePool team each daily using a contract function.

- Requirements:

+ Only the team can deposit rewards.
+ Deposited rewards go to the pool of users, not to individual users.
+ Users should be able to withdraw their deposits along with their share of rewards considering the time when they deposited.

NativePool provides a service where people can deposit native token and they will receive daily rewards. Users must be able to take out their deposits along with their portion of rewards at any time. New rewards are deposited manually into the pool by the NativePool team each daily using a contract function.

- Requirements:

* Only the team can deposit rewards.
* Deposited rewards go to the pool of users, not to individual users.
* Users should be able to withdraw their deposits along with their share of rewards considering the time when they deposited.

## Submission Requirements
- [ ] Finish `pallet-vesting`/ `pallet-native-pool` runtime
- [ ] Finish mocks and tests
- [ ] Record a video that run/simulate the logic on Polkadot JS explorer.
## Submission Requirements

- [x] Finish `pallet-vesting` runtime
- [x] Finish `pallet-native-pools` runtime
- [x] Finish mocks and tests
- [x] Record a video that run/simulate the logic on Polkadot JS explorer.

## How to run minimal template
## How to run minimal template

### Prerequisites

Completed the Install [Polkadot SDK Dependencies](https://docs.polkadot.com/develop/parachains/install-polkadot-sdk/) guide and successfully installed [Rust](https://www.rust-lang.org/) and the required packages to set up your development environment


### Step 1: Install `polkadot-omni-node`
### Step 1: Install `polkadot-omni-node`

```sh
cargo install --locked polkadot-omni-node@0.5.0
```

### Step 2: Install `staging-chain-spec-builder`
### Step 2: Install `staging-chain-spec-builder`

```sh
cargo install --locked staging-chain-spec-builder@10.0.0
```

### Step 3: Build both node & runtime
### Step 3: Build both node & runtime

```sh
cargo build --workspace --release
Expand All @@ -63,7 +59,6 @@ chain-spec-builder create --relay-chain "dev" --para-id 1000 --runtime \
target/release/wbuild/minimal-template-runtime/minimal_template_runtime.wasm named-preset development
```


### Step 5: Run Omni Node

Start Omni Node in development mode (sets up block production and finalization based on manual seal,
Expand All @@ -73,7 +68,149 @@ sealing a new block every 3 seconds), with a minimal template runtime chain spec
polkadot-omni-node --chain <path/to/chain_spec.json> --dev
```

## Submissions for vesting pallets

### Test cases all pass

![Vesting](https://drive.google.com/uc?export=view&id=1_1PWkrvosrhVsRXEmzoKfoVbo8vzYYPN)

Add additional test case for `force_remove_vesting_schedule`

```
#[test]
fn force_remove_vesting_schedule_works() {
ExtBuilder::build().execute_with(|| {
System::set_block_number(1);
// Create two vesting schedules
let schedule1 = VestingSchedule {
start: 2u64,
period: 10u64,
period_count: 3u32,
per_period: 100u64,
}; // total=300
let schedule2 = VestingSchedule {
start: 5u64,
period: 5u64,
period_count: 4u32,
per_period: 50u64,
}; // total=200

// Create vesting schedules for BOB
assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), BOB, schedule1));
assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), BOB, schedule2.clone()));

// Verify initial state
let total_transferred = 300 + 200;
assert_eq!(PalletBalances::free_balance(&BOB), total_transferred);
let initial_schedules = VestingSchedules::<Runtime>::get(&BOB);
assert_eq!(initial_schedules.len(), 2);

// Try to remove schedule with non-root origin (should fail)
assert_noop!(
Vesting::force_remove_vesting_schedule(RuntimeOrigin::signed(ALICE), BOB, 0),
DispatchError::BadOrigin
);

// Try to remove schedule with invalid index (should fail)
assert_noop!(
Vesting::force_remove_vesting_schedule(RuntimeOrigin::root(), BOB, 2),
Error::<Runtime>::InvalidVestingIndex
);

// Remove first schedule (index 0)
assert_ok!(Vesting::force_remove_vesting_schedule(RuntimeOrigin::root(), BOB, 0));

// Verify state after removal
let remaining_schedules = VestingSchedules::<Runtime>::get(&BOB);
assert_eq!(remaining_schedules.len(), 1);
assert_eq!(remaining_schedules[0], schedule2);

// Verify lock amount is updated
let locks = PalletBalances::locks(&BOB);
assert_eq!(locks[0].amount, 200); // Only schedule2 remains (200 total)

// Remove second schedule (index 0 since we removed the first one)
assert_ok!(Vesting::force_remove_vesting_schedule(RuntimeOrigin::root(), BOB, 0));

// Verify all schedules are removed
let final_schedules = VestingSchedules::<Runtime>::get(&BOB);
assert_eq!(final_schedules.len(), 0);

// Verify lock is removed
let final_locks = PalletBalances::locks(&BOB);
assert_eq!(final_locks.len(), 0);
});
}
```

### Click on the below images to watch the video.

### Successful Vested Transfer And Claiming Vested Tokens

This simulation shows:

- a standard vested_transfer works correctly, locks the funds, and creates a vesting schedule. It corresponds to `vested_transfer_works` in `tests.rs`.

- a recipient can claim tokens that have vested over time. It corresponds to `claim_works` in `tests.rs`.

Video:

```
https://youtu.be/qiq1HjmwqoA
```

[![Successful Vested Transfer And Claiming Vested Tokens](https://img.youtube.com/vi/qiq1HjmwqoA/maxresdefault.jpg)](https://youtu.be/qiq1HjmwqoA)

### Invalid Vesting Schedule Parameters

This simulation ensures that a `vested_transfer` will fail if the schedule has a period or period count of zero. It corresponds to `vested_transfer_fails_if_zero_period_or_count` in `tests.rs`.

Video:

```
https://youtu.be/AbTQ29Ja5MY
```

[![Invalid Vesting Schedule Parameters](https://img.youtube.com/vi/AbTQ29Ja5MY/maxresdefault.jpg)](https://youtu.be/AbTQ29Ja5MY)

### Updating Vesting Schedules (Sudo)

This simulation shows that a privileged account (Root origin) can update the vesting schedules for any account. It corresponds to `update_vesting_schedules_works` in `tests.rs`.

Video:

```
https://youtu.be/OebEBDlAetk
```

[![Updating Vesting Schedules (Sudo)](https://img.youtube.com/vi/OebEBDlAetk/maxresdefault.jpg)](https://youtu.be/OebEBDlAetk)

### Force remove vesting schedules

This simulation shows the logic when force remove vesting schedules. It corresponds to `force_remove_vesting_schedule_works` in `tests.rs`.

Video:

```
https://youtu.be/_Dn5y5Ns4tU
```

[![Force remove vesting schedules](https://img.youtube.com/vi/_Dn5y5Ns4tU/maxresdefault.jpg)](https://youtu.be/_Dn5y5Ns4tU)

### Claiming with Multiple Schedules

This simulation shows the claim logic when an account has multiple, overlapping vesting schedules. It corresponds to `multiple_vesting_schedule_claim_works` in `tests.rs`.

Video:

```
https://youtu.be/GQZQAUFtbQw
```

[![Claiming with Multiple Schedules](https://img.youtube.com/vi/GQZQAUFtbQw/maxresdefault.jpg)](https://youtu.be/GQZQAUFtbQw)

## Submissions for native_pools pallets

### Test cases pass

![Native Pools Test](https://drive.google.com/uc?export=view&id=1Ru212gEM_lH6zcg-6XTa5vm41xGOxUFM)
68 changes: 7 additions & 61 deletions challenge-4-polkadot-sdk/chain_spec.json

Large diffs are not rendered by default.

Binary file added challenge-4-polkadot-sdk/images/.DS_Store
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added challenge-4-polkadot-sdk/images/tests-vesting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions challenge-4-polkadot-sdk/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
vec![
get_account_id_from_seed::<sr25519::Public>("//Alice"),
get_account_id_from_seed::<sr25519::Public>("//Bob"),
get_account_id_from_seed::<sr25519::Public>("//Charlie"),
],
get_account_id_from_seed::<sr25519::Public>("//Alice"),
))
Expand Down
4 changes: 2 additions & 2 deletions challenge-4-polkadot-sdk/node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub fn run() -> sc_cli::Result<()> {
None => {
let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move {
match config.network.network_backend.unwrap_or_default() {
match config.network.network_backend {
sc_network::config::NetworkBackendType::Libp2p =>
service::new_full::<sc_network::NetworkWorker<_, _>>(config, cli.consensus)
.map_err(sc_cli::Error::Service),
Expand All @@ -129,4 +129,4 @@ pub fn run() -> sc_cli::Result<()> {
})
},
}
}
}
5 changes: 4 additions & 1 deletion challenge-4-polkadot-sdk/pallets/native-pools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ targets = ["x86_64-unknown-linux-gnu"]
codec = { features = ["derive"], workspace = true }
polkadot-sdk = { workspace = true, features = ["experimental", "runtime"], default-features = false }
scale-info = { features = ["derive"], workspace = true }

pallet-balances = { workspace = true }

[features]
default = ["std"]
std = ["codec/std", "polkadot-sdk/std", "scale-info/std"]

[dev-dependencies]
polkadot-sdk = { workspace = true, features = ["experimental", "runtime", "std", "pallet-balances"] }
Loading