如何避免在合约业务逻辑中做出基于时间的决策?
How to Avoid making time-based decisions in contract business logic?
我写了一个省钱的智能合约,用户存入 ETH 并定义他们希望在合约中保留该 ETH 的时间,例如:用户 X 存入 2ETH 一年,他们只能在之后提取 ETH那个时期。
但是 solidity linter 一直告诉我,我不应该依赖 block.timestamp
来做决定。
这是我用来将每个地址映射到余额和结束时间的 Saving
结构:
struct Saving {
uint256 balance;
uint256 endTime;
}
这是我的函数修饰符,我要求取款时间大于我在存款时存储的结束时间:
modifier onlyValidTimeWithdraw() {
require(
block.timestamp > balances[msg.sender].endTime,
"You cannot withdraw yet"
);
_;
}
这是我通过 linter 得到的消息。
经过一些研究后,我发现我的合约中不应该有时间依赖条件,因为矿工可以操纵时间戳,但我没有找到任何替代方案。
矿工可以在大约 10 个范围内操纵区块时间戳。几秒,足以影响到秒级精度的业务逻辑。
function betLottery() external {
// the block.timestamp can be affected by a miner
// and they can submit their own winning transaction
if (block.timestamp % 2 == 0) {
win();
}
}
但是由于您的逻辑依赖于更长的周期,所以我会忽略或取消警告。
或者如果它适合您的用例,您可以根据块号进行验证,大多数 linter 都允许这样做。
struct Saving {
uint256 balance;
uint256 endBlock;
}
require(
block.number > balances[msg.sender].endBlock,
"You cannot withdraw yet"
);
我写了一个省钱的智能合约,用户存入 ETH 并定义他们希望在合约中保留该 ETH 的时间,例如:用户 X 存入 2ETH 一年,他们只能在之后提取 ETH那个时期。
但是 solidity linter 一直告诉我,我不应该依赖 block.timestamp
来做决定。
这是我用来将每个地址映射到余额和结束时间的 Saving
结构:
struct Saving {
uint256 balance;
uint256 endTime;
}
这是我的函数修饰符,我要求取款时间大于我在存款时存储的结束时间:
modifier onlyValidTimeWithdraw() {
require(
block.timestamp > balances[msg.sender].endTime,
"You cannot withdraw yet"
);
_;
}
这是我通过 linter 得到的消息。
经过一些研究后,我发现我的合约中不应该有时间依赖条件,因为矿工可以操纵时间戳,但我没有找到任何替代方案。
矿工可以在大约 10 个范围内操纵区块时间戳。几秒,足以影响到秒级精度的业务逻辑。
function betLottery() external {
// the block.timestamp can be affected by a miner
// and they can submit their own winning transaction
if (block.timestamp % 2 == 0) {
win();
}
}
但是由于您的逻辑依赖于更长的周期,所以我会忽略或取消警告。
或者如果它适合您的用例,您可以根据块号进行验证,大多数 linter 都允许这样做。
struct Saving {
uint256 balance;
uint256 endBlock;
}
require(
block.number > balances[msg.sender].endBlock,
"You cannot withdraw yet"
);