Skip to content
Open
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
48 changes: 38 additions & 10 deletions scripts/setStages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,31 @@ interface StageConfig {
variableWalletLimitPath?: string;
}

function isValidDate(dateString: string): boolean {
const date = new Date(dateString);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this able to catch 2024-06-31 issue?

Copy link
Author

Choose a reason for hiding this comment

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

https://stackoverflow.com/questions/1214234/javascript-date-parsing-bug-fails-for-dates-in-june

Should be good based on this article, defining and using that will fix

Copy link
Contributor

Choose a reason for hiding this comment

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

image Seems `new Date()` will not fail

Copy link
Contributor

Choose a reason for hiding this comment

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

@FwazB I have suffered immensely from JS dates. It's a "whack a mole" problem. There's always another gotcha.

I am seeing seconds (from block.timestamp) used and date strings like @channing-magiceden is calling out. Something like this could be helpful, modify as necessary:

function isValidDate(date: string) {
  if (/^\d+$/.test(date)) {
    // Date expects milliseconds, * 1000 here if using seconds
    const milliSeconds = parseInt(date, 10);

    return isValidDateInMilliSeconds(milliSeconds);
  } else {
    return isValidDateString(date);
  }
}

function isValidDateInMilliSeconds(milliseconds: number) {
  return !isNaN(new Date(milliseconds).getDate());
}

function isValidDateString(dateString: string) {
  const [year, month, day] = dateString.split(/[-/]/).map(Number);
  const date = new Date(year, month - 1, day);

  if (
    !(
      date.getFullYear() === year &&
      date.getMonth() + 1 === month &&
      date.getDate() === day
    )
  ) {
    return false;
  } else {
    return !isNaN(date.getTime());
  }
}

But this has some things to be aware of as well:

isValidDate("20240631") === truebecause the regex will treat this as milliseconds.

But in general, with js dates you can split/compare the input against the date values to ensure they match.

return date instanceof Date && !isNaN(date.getTime());
}

function validateAndConvertDates(stage: StageConfig) {
const { startDate, endDate } = stage;

if (!isValidDate(startDate.toString()) || !isValidDate(endDate.toString())) {
throw new Error("Invalid start or end date");
}

const start = new Date(startDate);
const end = new Date(endDate);

if (end <= start) {
throw new Error("End date must be after start date");
}

const startTimeUnixSeconds = Math.floor(start.getTime() / 1000);
const endTimeUnixSeconds = Math.floor(end.getTime() / 1000);

return { startTimeUnixSeconds, endTimeUnixSeconds };
}

export const setStages = async (
args: ISetStagesParams,
hre: HardhatRuntimeEnvironment,
Expand Down Expand Up @@ -91,16 +116,19 @@ export const setStages = async (
}),
);

const stages = stagesConfig.map((s, i) => ({
price: ethers.utils.parseEther(s.price),
mintFee: s.mintFee ? ethers.utils.parseEther(s.mintFee) : 0,
maxStageSupply: s.maxSupply ?? 0,
walletLimit: s.walletLimit ?? 0,
merkleRoot: merkleRoots[i],
startTimeUnixSeconds: Math.floor(new Date(s.startDate).getTime() / 1000),
endTimeUnixSeconds: Math.floor(new Date(s.endDate).getTime() / 1000),
}));

const stages = stagesConfig.map((s, i) => {
const { startTimeUnixSeconds, endTimeUnixSeconds } = validateAndConvertDates(s);

return {
price: ethers.utils.parseEther(s.price),
mintFee: s.mintFee ? ethers.utils.parseEther(s.mintFee) : 0,
maxStageSupply: s.maxSupply ?? 0,
walletLimit: s.walletLimit ?? 0,
merkleRoot: merkleRoots[i],
startTimeUnixSeconds,
endTimeUnixSeconds,
};
});
console.log(
`Stage params: `,
JSON.stringify(
Expand Down