Skip to content
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

fix(protocol): fix bridge unpause will delay execution #16612

Merged
merged 7 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
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
6 changes: 4 additions & 2 deletions packages/protocol/contracts/L1/libs/LibUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ library LibUtils {
view
returns (bool)
{
uint256 deadline = _tsTimestamp.max(_lastUnpausedAt) + _windowMinutes * 60;
return block.timestamp >= deadline;
unchecked {
uint256 deadline = _tsTimestamp.max(_lastUnpausedAt) + _windowMinutes * 60;
return block.timestamp >= deadline;
}
}
}
19 changes: 17 additions & 2 deletions packages/protocol/contracts/bridge/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.24;

import "../common/EssentialContract.sol";
import "../libs/LibAddress.sol";
import "../libs/LibMath.sol";
import "../signal/ISignalService.sol";
import "./IBridge.sol";

Expand All @@ -13,6 +14,7 @@ import "./IBridge.sol";
/// @custom:security-contact security@taiko.xyz
contract Bridge is EssentialContract, IBridge {
using Address for address;
using LibMath for uint256;
using LibAddress for address;
using LibAddress for address payable;

Expand Down Expand Up @@ -190,7 +192,7 @@ contract Bridge is EssentialContract, IBridge {
}
}

if (block.timestamp >= invocationDelay + receivedAt) {
if (_isPostInvocationDelay(receivedAt, invocationDelay)) {
delete proofReceipt[msgHash];
messageStatus[msgHash] = Status.RECALLED;

Expand Down Expand Up @@ -262,7 +264,7 @@ contract Bridge is EssentialContract, IBridge {
}
}

if (block.timestamp >= invocationDelay + receivedAt) {
if (_isPostInvocationDelay(receivedAt, invocationDelay)) {
// If the gas limit is set to zero, only the owner can process the message.
if (_message.gasLimit == 0 && msg.sender != _message.destOwner) {
revert B_PERMISSION_DENIED();
Expand Down Expand Up @@ -646,4 +648,17 @@ contract Bridge is EssentialContract, IBridge {
return false;
}
}

function _isPostInvocationDelay(
uint256 _receivedAt,
uint256 _invocationDelay
)
private
view
returns (bool)
{
unchecked {
return block.timestamp >= _receivedAt.max(lastUnpausedAt) + _invocationDelay;
}
}
}
3 changes: 3 additions & 0 deletions packages/protocol/contracts/common/EssentialContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable,

uint8 private __paused;

uint64 public lastUnpausedAt;

uint256[49] private __gap;

/// @notice Emitted when the contract is paused.
Expand Down Expand Up @@ -81,6 +83,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable,
/// @notice Unpauses the contract.
function unpause() public virtual whenPaused {
__paused = _FALSE;
lastUnpausedAt = uint64(block.timestamp);
emit Unpaused(msg.sender);
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
Expand Down
12 changes: 10 additions & 2 deletions packages/protocol/contracts/team/TimelockTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,23 @@ contract TimelockTokenPool is EssentialContract, EIP712Upgradeable {
}

/// @notice Withdraws all withdrawable tokens.
function withdraw() external nonReentrant {
function withdraw() external whenNotPaused nonReentrant {
_withdraw(msg.sender, msg.sender);
}

/// @notice Withdraws all withdrawable tokens to a designated address.
/// @param _to The address where the granted and unlocked tokens shall be sent to.
/// @param _nonce The nonce to be used.
/// @param _sig Signature provided by the grant recipient.
function withdraw(address _to, uint256 _nonce, bytes memory _sig) external nonReentrant {
function withdraw(
address _to,
uint256 _nonce,
bytes calldata _sig
)
external
whenNotPaused
nonReentrant
{
if (_to == address(0)) revert INVALID_PARAM();

address account = ECDSA.recover(getWithdrawalHash(_to, _nonce), _sig);
Expand Down
Loading