-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bid Status Visibility #42
Conversation
anihamde
commented
Apr 4, 2024
•
edited
Loading
edited
- enable historical bid queries by querying directly from database
- add an event to ExpressRelay contract to make included bids more visible on-chain
- add auction table
- create query for auction based on permission key
- add tx hash to Lost status
CREATE TABLE auction | ||
( | ||
id UUID PRIMARY KEY, | ||
conclusion_time TIMESTAMP NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add another column creation_time
with default current_timestamp
to keep track of when we have added this row to the db. This can be helpful next to this conclusion_time
to measure latency, etc.
auction-server/src/api/auction.rs
Outdated
pub params: AuctionParams, | ||
} | ||
|
||
/// Query for auctions with the permission key and (optionally) chain ID specified. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure who is gonna use this endpoint, let's discuss the access patterns and how we want searchers to have more visibility.
auction-server/src/api/auction.rs
Outdated
Ok(Json(auctions)) | ||
} | ||
|
||
// Get auction with the specified ID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no additional information in this comment.
auction-server/src/api/auction.rs
Outdated
let auction = sqlx::query!("SELECT * FROM auction WHERE id = $1", auction_id) | ||
.fetch_one(&store.db) | ||
.await | ||
.map_err(|_| RestError::BidNotFound)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be AuctionNotFound
auction-server/src/api/auction.rs
Outdated
params: AuctionParams { | ||
chain_id: auction.chain_id, | ||
permission_key: auction.permission_key.into(), | ||
tx_hash: H256::from_slice(auction.tx_hash.as_ref()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from_slice
can panic. Isn't there any safer way to do this?
) -> anyhow::Result<()> { | ||
if update.bid_status == BidStatus::Pending { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can keep this as an additional safety measure.
bytes indexed permissionKey, | ||
uint256 indexed multicallIndex, | ||
uint256 bidAmount, | ||
bool externalSuccess, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't we just use the MulticallStatus
type here?
pragma solidity ^0.8.13; | ||
|
||
contract ExpressRelayEvents { | ||
event ReceivedETH(address indexed sender, uint256 amount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indexed
adds some additional gas IIRC. Let's make sure this is worth it.
event ReceivedETH(address indexed sender, uint256 amount); | ||
event MulticallIssued( | ||
bytes indexed permissionKey, | ||
uint256 indexed multicallIndex, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we replace this with bid-id? I think it will become much easier for searchers to listen to an event with the specific bid id we returned to them at the time of bid submission. Otherwise they have to wait until auction conclusion to get this multicallIndex. Otherwise, they have to use (tx_hash, permission_key,multicall_index) as the unique key for identifying their bid.
@@ -10,6 +10,5 @@ CREATE TABLE bid | |||
target_calldata BYTEA NOT NULL, | |||
bid_amount NUMERIC(78, 0) NOT NULL, | |||
status bid_status NOT NULL, | |||
auction_id UUID, -- TODO: should be linked to the auction table in the future | |||
removal_time TIMESTAMP -- TODO: should be removed and read from the auction table in the future | |||
auction_id UUID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add another column here that shows the position of this bid in the bundle. Having a null value while having an auction id means that this bid was not submitted on-chain (it lost)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a foreign key with protect constraint.
@@ -51,7 +51,7 @@ pub struct OpportunityParamsWithMetadata { | |||
opportunity_id: OpportunityId, | |||
/// Creation time of the opportunity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add a comment that this is in nanoseconds, also change the example to a more realistic value
auction-server/src/state.rs
Outdated
pub async fn update_auction(&self, auction: AuctionParamsWithMetadata) -> anyhow::Result<()> { | ||
let conclusion_datetime = | ||
OffsetDateTime::from_unix_timestamp_nanos(auction.conclusion_time)?; | ||
sqlx::query!("UPDATE auction SET conclusion_time = $1, tx_hash = $2 WHERE id = $3 AND permission_key = $4 AND chain_id = $5 AND conclusion_time IS NULL", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get why we need AND permission_key = $4 AND chain_id = $5
. Auction id is unique alone right?
@@ -51,7 +51,7 @@ pub struct OpportunityParamsWithMetadata { | |||
opportunity_id: OpportunityId, | |||
/// Creation time of the opportunity | |||
#[schema(example = 1700000000, value_type = i64)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i128?
auction-server/src/state.rs
Outdated
#[schema(example = "0x103d4fbd777a36311b5161f2062490f761f25b67406badb2bace62bb170aa4e3", value_type = String)] | ||
result: H256, | ||
#[schema(example = 1, value_type = u64)] | ||
index: U256, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can just use u64 or even u32 here
@@ -587,7 +587,13 @@ contract ExpressRelayTestSetup is | |||
|
|||
multicallData = new MulticallData[](contracts.length); | |||
for (uint i = 0; i < contracts.length; i++) { | |||
bytes16 bidId = bytes16( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this gives a false hint that this is how we construct the id. I'd rather use something simpler like bytes16(keccak256("randomstuff"))
or even simpler than this if possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is to allow us to have distinct bid ids for future tests, that we can easily recover. i'll precede this construction with something like what you've suggested to make it clear this is not a valid construction
@@ -216,6 +230,7 @@ pub struct Store { | |||
} | |||
|
|||
impl Store { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's easy enough to find this out looking at the implementations. I'm not a big fan of comments TBH. Also, some comments are misleading here.
remove_opportunity
and broadcast_bid_status_and_remove
do not state that they access db
auction-server/src/api/bid.rs
Outdated
match store.bids.read().await.get(&bid_id) { | ||
Some(bid) => Ok(bid.status.clone().into()), | ||
None => Err(RestError::BidNotFound), | ||
let status_data = sqlx::query!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this to state. Also no need to have 2 separate queries, we can join these 2 tables and have a single query. I think the code will become simpler.
auction-server/src/api.rs
Outdated
@@ -75,7 +83,11 @@ pub enum RestError { | |||
InvalidChainId, | |||
/// The simulation failed | |||
SimulationError { result: Bytes, reason: String }, | |||
/// The order was not found | |||
/// The auction was not concluded | |||
AuctionNotConcluded, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should not be an error, Pending is a valid status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is only called in get_concluded_auction
, where we expect the auction being queried to have been concluded
Submitted { | ||
#[schema(example = "0x103d4fbd777a36311b5161f2062490f761f25b67406badb2bace62bb170aa4e3", value_type = String)] | ||
result: H256, | ||
#[schema(example = 1, value_type = u32)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to specify value_type if it's the same
/// Creation time of the opportunity | ||
#[schema(example = 1700000000, value_type = i64)] | ||
creation_time: UnixTimestamp, | ||
/// Creation time of the opportunity (in nanoseconds since the Unix epoch) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update the comment
#[schema(example = 1700000000, value_type = i64)] | ||
creation_time: UnixTimestamp, | ||
/// Creation time of the opportunity (in nanoseconds since the Unix epoch) | ||
#[schema(example = 1_700_000_000_000_000i128, value_type = i128)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this still fits in i64. No need to introduce i128