Skip to content

feat: add storage helper#130

Closed
beebozy wants to merge 3 commits intoAlien-Protocol:mainfrom
beebozy:feature-storage-helper
Closed

feat: add storage helper#130
beebozy wants to merge 3 commits intoAlien-Protocol:mainfrom
beebozy:feature-storage-helper

Conversation

@beebozy
Copy link
Copy Markdown

@beebozy beebozy commented Mar 24, 2026

hi, kindly go through the implementation.. Closes #95

Summary by CodeRabbit

  • New Features
    • Complete auction system: create auctions with start/end times and reserve price.
    • Bidding flow: bidders can place bids and highest bid/bidder are tracked in real time.
    • Persistence and bidder tracking: auctions, individual bids, and bidder lists are stored and queryable.
    • Query APIs to fetch auction state, a bidder's bid, and the full bidder list.

@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 24, 2026

@beebozy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c3f9f57-518b-4b85-9cea-67e15fd1326c

📥 Commits

Reviewing files that changed from the base of the PR and between 1c73d1b and 993da7a.

📒 Files selected for processing (1)
  • gateway-contract/contracts/auction_contract/src/types.rs

📝 Walkthrough

Walkthrough

Replaces a stub auction contract with a full auction implementation: new types (AuctionState, Bid), a storage module with CRUD helpers and TTL management, and public contract methods to create auctions, place bids, and query auctions/bids/bidders.

Changes

Cohort / File(s) Summary
Contract API
gateway-contract/contracts/auction_contract/src/lib.rs
Added public contract methods: create_auction, get_auction, has_auction, place_bid, get_bid, get_all_bidders. Re-exports storage and type items for external use and enforces auth/validation in entry points.
Storage Layer
gateway-contract/contracts/auction_contract/src/storage.rs
New DataKey enum and seven persistent helpers: get_auction, set_auction, has_auction, get_bid, set_bid, get_all_bidders, add_bidder. Helpers extend TTL and add_bidder deduplicates bidders.
Data Types
gateway-contract/contracts/auction_contract/src/types.rs
Introduced #[contracttype] structs AuctionState and Bid (fields: creator, timing, pricing, highest bid/bidder, settled flag; bidder, amount, timestamp). Removed several prior enum key types.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Contract as Auction Contract
    participant Storage as On-Chain Storage

    Client->>Contract: create_auction(creator, hash, start_time, end_time, reserve_price)
    activate Contract
    Contract->>Contract: creator.require_auth()
    Contract->>Storage: has_auction(hash)
    Storage-->>Contract: false
    Contract->>Storage: set_auction(hash, AuctionState)
    Storage-->>Contract: OK
    Contract-->>Client: OK
    deactivate Contract
Loading
sequenceDiagram
    participant Client
    participant Contract as Auction Contract
    participant Storage as On-Chain Storage

    Client->>Contract: place_bid(hash, bidder, amount)
    activate Contract
    Contract->>Contract: bidder.require_auth()
    Contract->>Storage: get_auction(hash)
    Storage-->>Contract: AuctionState
    Contract->>Contract: assert(amount > highest_bid)
    Contract->>Storage: get_all_bidders(hash)
    Storage-->>Contract: Vec<Address>
    Contract->>Storage: add_bidder(hash, bidder)
    Storage-->>Contract: OK
    Contract->>Storage: set_bid(hash, bidder, Bid)
    Storage-->>Contract: OK
    Contract->>Storage: set_auction(hash, updated_state)
    Storage-->>Contract: OK
    Contract-->>Client: OK
    deactivate Contract
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Approved

Suggested reviewers

  • ryzen-xp

Poem

🐇 I hopped through bytes and storage bins,

Built auctions where the bidding begins,
Bids recorded, states held tight,
Ledger timestamps shining bright,
A rabbit cheers — the contract's right! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes significant changes to lib.rs and types.rs beyond the storage.rs helpers specified in issue #95, adding contract methods like create_auction and place_bid which are out of scope. Focus this PR on implementing only the storage helpers and DataKey enum in storage.rs as required by issue #95. Move contract method implementations (create_auction, place_bid, etc.) to a separate PR.
Title check ❓ Inconclusive The PR title 'feat: add storage helper' is vague and generic, using 'storage helper' without specifying which storage helpers are being added or their purpose. Clarify the title to explicitly mention the storage helpers being added, e.g., 'feat: add auction storage helpers' or 'feat: implement DataKey enum and storage CRUD functions'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR implements all required storage helpers and the DataKey enum as specified in issue #95. All seven required functions and the DataKey enum are present, and helpers are imported and used in lib.rs.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@gateway-contract/contracts/auction_contract/src/lib.rs`:
- Around line 30-51: The create_auction function lacks validation of time
bounds; update create_auction to assert that end_time > start_time and also
check start_time is not in the past by comparing start_time against the current
ledger timestamp (obtainable from Env via env.ledger().timestamp() or
equivalent), returning/aborting with a clear error message if either check
fails; keep the existing creator.require_auth() and has_auction check and
perform these time validations before constructing and calling set_auction.
- Around line 78-98: place_bid currently allows bids after auction end or after
settlement and never enforces the reserve price; update place_bid to (1) fetch
env.ledger().timestamp() into a variable and assert timestamp <= state.end_time
with a clear message, (2) assert state.is_settled == false, and (3) enforce
reserve price for the first meaningful bid by requiring that if
state.highest_bid is 0 (or None depending on representation) the incoming amount
>= state.reserve_price, otherwise require amount > state.highest_bid; reference
the existing symbols place_bid, get_auction, state.end_time, state.is_settled,
state.reserve_price, state.highest_bid, and env.ledger().timestamp() when adding
these checks before creating and recording the Bid.

In `@gateway-contract/contracts/auction_contract/src/storage.rs`:
- Around line 223-246: The doc comment in add_bidder refers to a non-existent
MAX_BATCH_SIZE; either remove or correct that reference: update the comment
above pub fn add_bidder to state that deduplication is O(n) and relies on
caller-enforced bounds (or the protocol-level expected small bidder count), or
alternatively define a concrete constant (e.g. MAX_BIDDERS) and enforce it where
bidders are added (check length in add_bidder after loading
DataKey::AllBidders(hash) and return/error if >= MAX_BIDDERS) so the
documentation matches the actual enforcement; ensure you modify the
DataKey::AllBidders/add_bidder comment and any caller sites that should enforce
the bound to keep behavior consistent.

In `@gateway-contract/contracts/auction_contract/src/types.rs`:
- Line 1: Remove the unused imports BytesN, Env, and Vec from the top-level use
statement in types.rs so only contracttype and Address are imported; locate the
use line that currently reads use soroban_sdk::{contracttype, Address, BytesN,
Env, Vec}; and edit it to import only contracttype and Address to resolve the
build failure caused by unused imports.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6622892d-29a7-4cd9-bde9-dbc0091e3b32

📥 Commits

Reviewing files that changed from the base of the PR and between a30ab14 and 1c73d1b.

📒 Files selected for processing (3)
  • gateway-contract/contracts/auction_contract/src/lib.rs
  • gateway-contract/contracts/auction_contract/src/storage.rs
  • gateway-contract/contracts/auction_contract/src/types.rs

Comment on lines +30 to +51
pub fn create_auction(
env: Env,
creator: Address,
hash: BytesN<32>,
start_time: u64,
end_time: u64,
reserve_price: i128,
) {
creator.require_auth();
assert!(!has_auction(&env, &hash), "auction already exists");

let state = AuctionState {
creator,
start_time,
end_time,
reserve_price,
highest_bid: 0,
highest_bidder: None,
is_settled: false,
};
set_auction(&env, &hash, &state);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing validation for auction time constraints.

The function doesn't validate that end_time > start_time. An auction with invalid time bounds would be permanently unusable since bids could never be placed within a valid window. Consider also validating that start_time is not in the past.

🛡️ Proposed fix
 pub fn create_auction(
     env: Env,
     creator: Address,
     hash: BytesN<32>,
     start_time: u64,
     end_time: u64,
     reserve_price: i128,
 ) {
     creator.require_auth();
     assert!(!has_auction(&env, &hash), "auction already exists");
+    assert!(end_time > start_time, "end_time must be after start_time");
+    assert!(reserve_price >= 0, "reserve_price cannot be negative");

     let state = AuctionState {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn create_auction(
env: Env,
creator: Address,
hash: BytesN<32>,
start_time: u64,
end_time: u64,
reserve_price: i128,
) {
creator.require_auth();
assert!(!has_auction(&env, &hash), "auction already exists");
let state = AuctionState {
creator,
start_time,
end_time,
reserve_price,
highest_bid: 0,
highest_bidder: None,
is_settled: false,
};
set_auction(&env, &hash, &state);
}
pub fn create_auction(
env: Env,
creator: Address,
hash: BytesN<32>,
start_time: u64,
end_time: u64,
reserve_price: i128,
) {
creator.require_auth();
assert!(!has_auction(&env, &hash), "auction already exists");
assert!(end_time > start_time, "end_time must be after start_time");
assert!(reserve_price >= 0, "reserve_price cannot be negative");
let state = AuctionState {
creator,
start_time,
end_time,
reserve_price,
highest_bid: 0,
highest_bidder: None,
is_settled: false,
};
set_auction(&env, &hash, &state);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway-contract/contracts/auction_contract/src/lib.rs` around lines 30 - 51,
The create_auction function lacks validation of time bounds; update
create_auction to assert that end_time > start_time and also check start_time is
not in the past by comparing start_time against the current ledger timestamp
(obtainable from Env via env.ledger().timestamp() or equivalent),
returning/aborting with a clear error message if either check fails; keep the
existing creator.require_auth() and has_auction check and perform these time
validations before constructing and calling set_auction.

Comment on lines +78 to +98
pub fn place_bid(env: Env, hash: BytesN<32>, bidder: Address, amount: i128) {
bidder.require_auth();

let mut state = get_auction(&env, &hash).expect("auction not found");
assert!(amount > state.highest_bid, "bid must exceed highest bid");

let bid = Bid {
bidder: bidder.clone(),
amount,
timestamp: env.ledger().timestamp(),
};

// Update the bidder list before writing the bid record so that the
// AllBidders key is always at least as fresh as any Bid key.
add_bidder(&env, &hash, bidder.clone());
set_bid(&env, &hash, &bidder, &bid);

state.highest_bid = amount;
state.highest_bidder = Some(bidder);
set_auction(&env, &hash, &state);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing critical bid validation: auction must be active and not settled.

place_bid allows bids on auctions that have ended (env.ledger().timestamp() > end_time) or been settled (is_settled == true). Additionally, the first bid should meet or exceed reserve_price, but this is never checked.

🔧 Proposed fix
 pub fn place_bid(env: Env, hash: BytesN<32>, bidder: Address, amount: i128) {
     bidder.require_auth();

     let mut state = get_auction(&env, &hash).expect("auction not found");
+    let now = env.ledger().timestamp();
+    assert!(!state.is_settled, "auction is already settled");
+    assert!(now >= state.start_time, "auction has not started");
+    assert!(now <= state.end_time, "auction has ended");
     assert!(amount > state.highest_bid, "bid must exceed highest bid");
+    assert!(amount >= state.reserve_price, "bid must meet reserve price");

     let bid = Bid {
         bidder: bidder.clone(),
         amount,
-        timestamp: env.ledger().timestamp(),
+        timestamp: now,
     };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn place_bid(env: Env, hash: BytesN<32>, bidder: Address, amount: i128) {
bidder.require_auth();
let mut state = get_auction(&env, &hash).expect("auction not found");
assert!(amount > state.highest_bid, "bid must exceed highest bid");
let bid = Bid {
bidder: bidder.clone(),
amount,
timestamp: env.ledger().timestamp(),
};
// Update the bidder list before writing the bid record so that the
// AllBidders key is always at least as fresh as any Bid key.
add_bidder(&env, &hash, bidder.clone());
set_bid(&env, &hash, &bidder, &bid);
state.highest_bid = amount;
state.highest_bidder = Some(bidder);
set_auction(&env, &hash, &state);
}
pub fn place_bid(env: Env, hash: BytesN<32>, bidder: Address, amount: i128) {
bidder.require_auth();
let mut state = get_auction(&env, &hash).expect("auction not found");
let now = env.ledger().timestamp();
assert!(!state.is_settled, "auction is already settled");
assert!(now >= state.start_time, "auction has not started");
assert!(now <= state.end_time, "auction has ended");
assert!(amount > state.highest_bid, "bid must exceed highest bid");
assert!(amount >= state.reserve_price, "bid must meet reserve price");
let bid = Bid {
bidder: bidder.clone(),
amount,
timestamp: now,
};
// Update the bidder list before writing the bid record so that the
// AllBidders key is always at least as fresh as any Bid key.
add_bidder(&env, &hash, bidder.clone());
set_bid(&env, &hash, &bidder, &bid);
state.highest_bid = amount;
state.highest_bidder = Some(bidder);
set_auction(&env, &hash, &state);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway-contract/contracts/auction_contract/src/lib.rs` around lines 78 - 98,
place_bid currently allows bids after auction end or after settlement and never
enforces the reserve price; update place_bid to (1) fetch
env.ledger().timestamp() into a variable and assert timestamp <= state.end_time
with a clear message, (2) assert state.is_settled == false, and (3) enforce
reserve price for the first meaningful bid by requiring that if
state.highest_bid is 0 (or None depending on representation) the incoming amount
>= state.reserve_price, otherwise require amount > state.highest_bid; reference
the existing symbols place_bid, get_auction, state.end_time, state.is_settled,
state.reserve_price, state.highest_bid, and env.ledger().timestamp() when adding
these checks before creating and recording the Bid.

Comment on lines +223 to +246
/// # Implementation note
/// The deduplication check is O(n) in the number of existing bidders. This
/// is acceptable because the number of bidders per auction is bounded by
/// `MAX_BATCH_SIZE` enforced at the call site in `lib.rs`.
pub fn add_bidder(env: &Env, hash: &BytesN<32>, bidder: Address) {
let key = DataKey::AllBidders(hash.clone());
let mut bidders: Vec<Address> = env
.storage()
.persistent()
.get(&key)
.unwrap_or_else(|| Vec::new(env));

// Deduplication: only append if the address is not already in the list.
for existing in bidders.iter() {
if existing == bidder {
return;
}
}

bidders.push_back(bidder);
env.storage().persistent().set(&key, &bidders);
env.storage()
.persistent()
.extend_ttl(&key, LEDGER_THRESHOLD, LEDGER_BUMP);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for MAX_BATCH_SIZE definition in the codebase
rg -n 'MAX_BATCH_SIZE' --type rust

Repository: Alien-Protocol/Alien-Gateway

Length of output: 194


Remove or clarify the reference to MAX_BATCH_SIZE in the documentation comment.

The comment references MAX_BATCH_SIZE as a bound enforced at the call site, but this constant does not exist in the codebase. Either define this constant and enforce it, or update the documentation to accurately describe the actual bounds/safeguards in place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway-contract/contracts/auction_contract/src/storage.rs` around lines 223
- 246, The doc comment in add_bidder refers to a non-existent MAX_BATCH_SIZE;
either remove or correct that reference: update the comment above pub fn
add_bidder to state that deduplication is O(n) and relies on caller-enforced
bounds (or the protocol-level expected small bidder count), or alternatively
define a concrete constant (e.g. MAX_BIDDERS) and enforce it where bidders are
added (check length in add_bidder after loading DataKey::AllBidders(hash) and
return/error if >= MAX_BIDDERS) so the documentation matches the actual
enforcement; ensure you modify the DataKey::AllBidders/add_bidder comment and
any caller sites that should enforce the bound to keep behavior consistent.

@@ -0,0 +1,48 @@
use soroban_sdk::{contracttype, Address, BytesN, Env, Vec};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove unused imports to fix the build failure.

The pipeline is failing because BytesN, Env, and Vec are imported but never used in this file. Only contracttype and Address are needed.

🔧 Proposed fix
-use soroban_sdk::{contracttype, Address, BytesN, Env, Vec};
+use soroban_sdk::{contracttype, Address};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
use soroban_sdk::{contracttype, Address, BytesN, Env, Vec};
use soroban_sdk::{contracttype, Address};
🧰 Tools
🪛 GitHub Actions: Checks

[error] 1-1: cargo clippy failed: unused imports BytesN, Env, and Vec. Error: -D unused-imports implied by -D warnings.


[error] 1-1: Build failed for crate auction_contract due to previous error (clippy reported unused imports).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway-contract/contracts/auction_contract/src/types.rs` at line 1, Remove
the unused imports BytesN, Env, and Vec from the top-level use statement in
types.rs so only contracttype and Address are imported; locate the use line that
currently reads use soroban_sdk::{contracttype, Address, BytesN, Env, Vec}; and
edit it to import only contracttype and Address to resolve the build failure
caused by unused imports.

@ryzen-xp ryzen-xp added the CI Failed Please check why you CI is faileing fix your code label Mar 24, 2026
@ryzen-xp
Copy link
Copy Markdown
Contributor

@beebozy , fix this code today

@beebozy
Copy link
Copy Markdown
Author

beebozy commented Mar 28, 2026

Okay @ryzen-xp.. If you mean I should update the fork and re implement.. I won't be able to do it today.. tomorrow I should because, I have been busy outside of drips.. I hope you understand

@ryzen-xp ryzen-xp closed this Mar 29, 2026
@github-project-automation github-project-automation bot moved this from Todo to Done in Drip Wave Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI Failed Please check why you CI is faileing fix your code

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Auction] Implement storage helpers in storage.rs (get/set/has for AuctionState and Bid)

2 participants