Solidity合约部署后6分钟解锁提款函数的条件判断实现咨询
Great question—let's break this down step by step so you get exactly what you need for your staking contract's withdrawal lock.
1. 条件判断的位置:必须放在函数内部(且优先执行)
First off, Solidity doesn't allow executable logic like if (block.timestamp > 360) outside of function bodies—so this check has to live inside your withdraw function.
Even more importantly, you should place this check at the very start of the function. Your current code wraps all withdrawal logic in the if block, which means users who try to withdraw early will get a successful transaction that does nothing (super confusing!). Instead, we should fail fast: if the lock isn't expired, revert immediately with a clear error. This avoids wasting gas on unnecessary logic (like the updateReward modifier's work) and gives users explicit feedback.
2. block.timestamp > 360 is totally wrong for your use case
block.timestamp returns the current Unix timestamp (seconds since 1970-01-01 00:00:00). Comparing it to 360 means you're checking if the current time is after 6 minutes into 1970—which has been true for decades, so your lock does nothing at all.
What you actually need is to check if the current time is 360 seconds after your contract was deployed. To do this, store the contract's deployment timestamp in a state variable, then compare that plus 360 to the current block timestamp.
Modified Working Code
// Add an immutable state variable to store deployment time (saves gas, can't be tampered with) uint256 public immutable s_deployTime; // Initialize deployment time in your constructor constructor() { s_deployTime = block.timestamp; } // Define custom errors for clear, gas-efficient feedback (Solidity 0.8.4+) error WithdrawLocked__TooEarly(); error TransferFailed(); function withdraw(uint256 amount) external updateReward(msg.sender) nonReentrant { // Fail fast: Check withdrawal lock first if (block.timestamp <= s_deployTime + 360) { revert WithdrawLocked__TooEarly(); } // Proceed with withdrawal logic s_totalSupply -= amount; s_balances[msg.sender] -= amount; emit WithdrewStake(msg.sender, amount); bool success = s_stakingToken.transfer(msg.sender, amount); if (!success) { revert TransferFailed(); } }
Key Notes
immutablefor deployment time: This variable is set once at deployment and can't be changed, making it secure and gas-efficient.- Fail-fast revert: Users get a clear error message instead of a silent no-op, which is critical for UX and debugging.
- Correct lock logic:
s_deployTime + 360ensures withdrawals are only allowed 6 minutes after the contract goes live, exactly matching your requirement.
内容的提问来源于stack exchange,提问作者XYZT

