diff --git a/helix-contract/contracts/mapping-token/v3/GuardV3.sol b/helix-contract/contracts/mapping-token/v3/GuardV3.sol index c6aeddc..4c2623f 100644 --- a/helix-contract/contracts/mapping-token/v3/GuardV3.sol +++ b/helix-contract/contracts/mapping-token/v3/GuardV3.sol @@ -7,6 +7,7 @@ import "@zeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "@zeppelin-solidity/contracts/utils/math/SafeMath.sol"; import "./GuardRegistryV3.sol"; import "../interfaces/IWToken.sol"; +import "../../utils/TokenTransferHelper.sol"; contract GuardV3 is GuardRegistryV3, Pausable { using SafeMath for uint256; @@ -20,9 +21,14 @@ contract GuardV3 is GuardRegistryV3, Pausable { event TokenDeposit(address sender, uint256 id, uint256 timestamp, address token, address recipient, uint256 amount); event TokenClaimed(uint256 id); - constructor(address[] memory _guards, uint256 _threshold, uint256 _maxUnclaimableTime) { + constructor( + address[] memory _guards, + address _operator, + uint256 _threshold, + uint256 _maxUnclaimableTime + ) { maxUnclaimableTime = _maxUnclaimableTime; - operator = msg.sender; + operator = _operator; initialize(_guards, _threshold); } @@ -53,7 +59,8 @@ contract GuardV3 is GuardRegistryV3, Pausable { depositors[depositor] = enable; } - function setMaxUnclaimableTime(uint256 _maxUnclaimableTime) external onlyOperator { + function setMaxUnclaimableTime(uint256 _maxUnclaimableTime, bytes[] memory signatures) external { + verifyGuardSignatures(msg.sig, abi.encode(_maxUnclaimableTime), signatures); maxUnclaimableTime = _maxUnclaimableTime; } @@ -87,13 +94,13 @@ contract GuardV3 is GuardRegistryV3, Pausable { require(amount > 0, "Guard: Invalid amount to claim"); delete deposits[id]; if (isNative) { - require(IERC20(token).transferFrom(from, address(this), amount), "Guard: claim native token failed"); + TokenTransferHelper.safeTransferFrom(token, from, address(this), amount); uint256 balanceBefore = address(this).balance; IWToken(token).withdraw(amount); require(address(this).balance == balanceBefore.add(amount), "Guard: token is not wrapped by native token"); - payable(recipient).transfer(amount); + TokenTransferHelper.safeTransferNative(recipient, amount); } else { - require(IERC20(token).transferFrom(from, recipient, amount), "Guard: claim token failed"); + TokenTransferHelper.safeTransferFrom(token, from, recipient, amount); } emit TokenClaimed(id); } diff --git a/helix-contract/flatten/xtoken-v3/GuardV3.sol b/helix-contract/flatten/xtoken-v3/GuardV3.sol index 5d4a873..ee475f6 100644 --- a/helix-contract/flatten/xtoken-v3/GuardV3.sol +++ b/helix-contract/flatten/xtoken-v3/GuardV3.sol @@ -14,11 +14,144 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 2/6/2024 + * 2/20/2024 **/ pragma solidity ^0.8.17; +// File @zeppelin-solidity/contracts/token/ERC20/IERC20.sol@v4.7.3 +// License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom( + address from, + address to, + uint256 amount + ) external returns (bool); +} + +// File contracts/utils/TokenTransferHelper.sol +// License-Identifier: MIT + +library TokenTransferHelper { + function safeTransfer( + address token, + address receiver, + uint256 amount + ) internal { + (bool success, bytes memory data) = token.call(abi.encodeWithSelector( + IERC20.transfer.selector, + receiver, + amount + )); + require(success && (data.length == 0 || abi.decode(data, (bool))), "helix:transfer token failed"); + } + + function safeTransferFrom( + address token, + address sender, + address receiver, + uint256 amount + ) internal { + (bool success, bytes memory data) = token.call(abi.encodeWithSelector( + IERC20.transferFrom.selector, + sender, + receiver, + amount + )); + require(success && (data.length == 0 || abi.decode(data, (bool))), "helix:transferFrom token failed"); + } + + function safeTransferNative( + address receiver, + uint256 amount + ) internal { + (bool success,) = payable(receiver).call{value: amount}(""); + require(success, "helix:transfer native token failed"); + } +} + +// File contracts/mapping-token/interfaces/IWToken.sol +// License-Identifier: MIT + + +interface IWToken { + function deposit() external payable; + function withdraw(uint wad) external; +} + // File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) @@ -608,15 +741,6 @@ contract GuardRegistryV3 { } } -// File contracts/mapping-token/interfaces/IWToken.sol -// License-Identifier: MIT - - -interface IWToken { - function deposit() external payable; - function withdraw(uint wad) external; -} - // File @zeppelin-solidity/contracts/utils/Context.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) @@ -746,89 +870,6 @@ abstract contract Pausable is Context { } } -// File @zeppelin-solidity/contracts/token/ERC20/IERC20.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); -} - // File @zeppelin-solidity/contracts/utils/math/SafeMath.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) @@ -1065,6 +1106,7 @@ library SafeMath { + contract GuardV3 is GuardRegistryV3, Pausable { using SafeMath for uint256; @@ -1077,9 +1119,14 @@ contract GuardV3 is GuardRegistryV3, Pausable { event TokenDeposit(address sender, uint256 id, uint256 timestamp, address token, address recipient, uint256 amount); event TokenClaimed(uint256 id); - constructor(address[] memory _guards, uint256 _threshold, uint256 _maxUnclaimableTime) { + constructor( + address[] memory _guards, + address _operator, + uint256 _threshold, + uint256 _maxUnclaimableTime + ) { maxUnclaimableTime = _maxUnclaimableTime; - operator = msg.sender; + operator = _operator; initialize(_guards, _threshold); } @@ -1144,13 +1191,13 @@ contract GuardV3 is GuardRegistryV3, Pausable { require(amount > 0, "Guard: Invalid amount to claim"); delete deposits[id]; if (isNative) { - require(IERC20(token).transferFrom(from, address(this), amount), "Guard: claim native token failed"); + TokenTransferHelper.safeTransferFrom(token, from, address(this), amount); uint256 balanceBefore = address(this).balance; IWToken(token).withdraw(amount); require(address(this).balance == balanceBefore.add(amount), "Guard: token is not wrapped by native token"); - payable(recipient).transfer(amount); + TokenTransferHelper.safeTransferNative(recipient, amount); } else { - require(IERC20(token).transferFrom(from, recipient, amount), "Guard: claim token failed"); + TokenTransferHelper.safeTransferFrom(token, from, recipient, amount); } emit TokenClaimed(id); } diff --git a/helix-contract/flatten/xtoken-v3/MsglineMessager.sol b/helix-contract/flatten/xtoken-v3/MsglineMessager.sol index eab164b..c42b083 100644 --- a/helix-contract/flatten/xtoken-v3/MsglineMessager.sol +++ b/helix-contract/flatten/xtoken-v3/MsglineMessager.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 12/26/2023 + * 1/30/2024 **/ pragma solidity ^0.8.17; @@ -94,7 +94,7 @@ abstract contract Application { contract MsglineMessager is Application, AccessController { - IMessageLine public immutable msgline; + IMessageLine public msgline; struct RemoteMessager { uint256 msglineRemoteChainId; @@ -128,6 +128,10 @@ contract MsglineMessager is Application, AccessController { msgline = IMessageLine(_msgline); } + function setMsgline(address _msgline) onlyDao external { + msgline = IMessageLine(_msgline); + } + function setRemoteMessager(uint256 _appRemoteChainId, uint256 _msglineRemoteChainId, address _remoteMessager) onlyDao external { remoteMessagers[_appRemoteChainId] = RemoteMessager(_msglineRemoteChainId, _remoteMessager); } diff --git a/helix-contract/flatten/xtoken-v3/MsgportMessager.sol b/helix-contract/flatten/xtoken-v3/MsgportMessager.sol index e026e48..e0af84c 100644 --- a/helix-contract/flatten/xtoken-v3/MsgportMessager.sol +++ b/helix-contract/flatten/xtoken-v3/MsgportMessager.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 2/6/2024 + * 2/20/2024 **/ pragma solidity ^0.8.17; @@ -61,17 +61,17 @@ contract AccessController { } } -// File contracts/interfaces/IMessageLine.sol +// File contracts/interfaces/IMessagePort.sol // License-Identifier: MIT -interface IMessageLine { +interface IMessagePort { function send(uint256 toChainId, address toDapp, bytes calldata message, bytes calldata params) external payable; function fee(uint256 toChainId, address toDapp, bytes calldata message, bytes calldata params) external view returns (uint256); } abstract contract Application { - function _msgSender() internal view returns (address payable _line) { - _line = payable(msg.sender); + function _msgSender() internal view returns (address payable _port) { + _port = payable(msg.sender); } function _fromChainId() internal pure returns (uint256 _msgDataFromChainId) { @@ -82,7 +82,7 @@ abstract contract Application { } function _xmsgSender() internal pure returns (address payable _from) { - require(msg.data.length >= 20, "!line"); + require(msg.data.length >= 20, "!port"); assembly { _from := shr(96, calldataload(sub(calldatasize(), 20))) } @@ -94,7 +94,7 @@ abstract contract Application { contract MsgportMessager is Application, AccessController { - IMessageLine public msgport; + IMessagePort public msgport; struct RemoteMessager { uint256 msgportRemoteChainId; @@ -118,18 +118,18 @@ contract MsgportMessager is Application, AccessController { _; } - modifier onlyMsgline() { + modifier onlyMsgPort() { require(msg.sender == address(msgport), "invalid caller"); _; } constructor(address _dao, address _msgport) { _initialize(_dao); - msgport = IMessageLine(_msgport); + msgport = IMessagePort(_msgport); } - function setMsgline(address _msgport) onlyDao external { - msgport = IMessageLine(_msgport); + function setMsgPort(address _msgport) onlyDao external { + msgport = IMessagePort(_msgport); } function setRemoteMessager(uint256 _appRemoteChainId, uint256 _msgportRemoteChainId, address _remoteMessager) onlyDao external { @@ -169,7 +169,7 @@ contract MsgportMessager is Application, AccessController { ); } - function receiveMessage(uint256 _srcAppChainId, address _remoteAppAddress, address _localAppAddress, bytes memory _message) onlyMsgline external { + function receiveMessage(uint256 _srcAppChainId, address _remoteAppAddress, address _localAppAddress, bytes memory _message) onlyMsgPort external { uint256 srcChainId = _fromChainId(); RemoteMessager memory remoteMessager = remoteMessagers[_srcAppChainId]; require(srcChainId == remoteMessager.msgportRemoteChainId, "invalid remote chainid"); diff --git a/helix-contract/flatten/xtoken-v3/xTokenBacking.sol b/helix-contract/flatten/xtoken-v3/xTokenBacking.sol index 07f19e0..b3dcbc4 100644 --- a/helix-contract/flatten/xtoken-v3/xTokenBacking.sol +++ b/helix-contract/flatten/xtoken-v3/xTokenBacking.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 2/6/2024 + * 2/20/2024 **/ pragma solidity ^0.8.17; @@ -143,21 +143,21 @@ library TokenTransferHelper { } } -// File contracts/mapping-token/interfaces/IGuard.sol +// File contracts/mapping-token/interfaces/IWToken.sol // License-Identifier: MIT -interface IGuard { - function deposit(uint256 id, address token, address recipient, uint256 amount) external; +interface IWToken { + function deposit() external payable; + function withdraw(uint wad) external; } -// File contracts/mapping-token/interfaces/IWToken.sol +// File contracts/mapping-token/interfaces/IGuard.sol // License-Identifier: MIT -interface IWToken { - function deposit() external payable; - function withdraw(uint wad) external; +interface IGuard { + function deposit(uint256 id, address token, address recipient, uint256 amount) external; } // File contracts/interfaces/IMessager.sol diff --git a/helix-contract/flatten/xtoken-v3/xTokenErc20.sol b/helix-contract/flatten/xtoken-v3/xTokenErc20.sol index fb1625f..b8a9829 100644 --- a/helix-contract/flatten/xtoken-v3/xTokenErc20.sol +++ b/helix-contract/flatten/xtoken-v3/xTokenErc20.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 2/6/2024 + * 2/20/2024 **/ pragma solidity ^0.8.17; diff --git a/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol b/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol index 38790eb..19bfbd1 100644 --- a/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol +++ b/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 2/6/2024 + * 2/20/2024 **/ pragma solidity ^0.8.17; @@ -193,6 +193,19 @@ contract AccessController { } } +// File contracts/interfaces/IMessager.sol +// License-Identifier: MIT + +interface ILowLevelMessageSender { + function registerRemoteReceiver(uint256 remoteChainId, address remoteBridge) external; + function sendMessage(uint256 remoteChainId, bytes memory message, bytes memory params) external payable; +} + +interface ILowLevelMessageReceiver { + function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external; + function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; +} + // File contracts/utils/DailyLimit.sol // License-Identifier: MIT @@ -276,17 +289,133 @@ contract DailyLimit { } } -// File contracts/interfaces/IMessager.sol +// File @zeppelin-solidity/contracts/utils/Context.sol@v4.7.3 // License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) -interface ILowLevelMessageSender { - function registerRemoteReceiver(uint256 remoteChainId, address remoteBridge) external; - function sendMessage(uint256 remoteChainId, bytes memory message, bytes memory params) external payable; + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } } -interface ILowLevelMessageReceiver { - function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external; - function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; +// File @zeppelin-solidity/contracts/security/Pausable.sol@v4.7.3 +// License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) + + +/** + * @dev Contract module which allows children to implement an emergency stop + * mechanism that can be triggered by an authorized account. + * + * This module is used through inheritance. It will make available the + * modifiers `whenNotPaused` and `whenPaused`, which can be applied to + * the functions of your contract. Note that they will not be pausable by + * simply including this module, only once the modifiers are put in place. + */ +abstract contract Pausable is Context { + /** + * @dev Emitted when the pause is triggered by `account`. + */ + event Paused(address account); + + /** + * @dev Emitted when the pause is lifted by `account`. + */ + event Unpaused(address account); + + bool private _paused; + + /** + * @dev Initializes the contract in unpaused state. + */ + constructor() { + _paused = false; + } + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + * + * Requirements: + * + * - The contract must not be paused. + */ + modifier whenNotPaused() { + _requireNotPaused(); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + * + * Requirements: + * + * - The contract must be paused. + */ + modifier whenPaused() { + _requirePaused(); + _; + } + + /** + * @dev Returns true if the contract is paused, and false otherwise. + */ + function paused() public view virtual returns (bool) { + return _paused; + } + + /** + * @dev Throws if the contract is paused. + */ + function _requireNotPaused() internal view virtual { + require(!paused(), "Pausable: paused"); + } + + /** + * @dev Throws if the contract is not paused. + */ + function _requirePaused() internal view virtual { + require(paused(), "Pausable: not paused"); + } + + /** + * @dev Triggers stopped state. + * + * Requirements: + * + * - The contract must not be paused. + */ + function _pause() internal virtual whenNotPaused { + _paused = true; + emit Paused(_msgSender()); + } + + /** + * @dev Returns to normal state. + * + * Requirements: + * + * - The contract must be paused. + */ + function _unpause() internal virtual whenPaused { + _paused = false; + emit Unpaused(_msgSender()); + } } // File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 @@ -649,135 +778,6 @@ abstract contract Initializable { } } -// File @zeppelin-solidity/contracts/utils/Context.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - -// File @zeppelin-solidity/contracts/security/Pausable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) - - -/** - * @dev Contract module which allows children to implement an emergency stop - * mechanism that can be triggered by an authorized account. - * - * This module is used through inheritance. It will make available the - * modifiers `whenNotPaused` and `whenPaused`, which can be applied to - * the functions of your contract. Note that they will not be pausable by - * simply including this module, only once the modifiers are put in place. - */ -abstract contract Pausable is Context { - /** - * @dev Emitted when the pause is triggered by `account`. - */ - event Paused(address account); - - /** - * @dev Emitted when the pause is lifted by `account`. - */ - event Unpaused(address account); - - bool private _paused; - - /** - * @dev Initializes the contract in unpaused state. - */ - constructor() { - _paused = false; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - * - * Requirements: - * - * - The contract must not be paused. - */ - modifier whenNotPaused() { - _requireNotPaused(); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - * - * Requirements: - * - * - The contract must be paused. - */ - modifier whenPaused() { - _requirePaused(); - _; - } - - /** - * @dev Returns true if the contract is paused, and false otherwise. - */ - function paused() public view virtual returns (bool) { - return _paused; - } - - /** - * @dev Throws if the contract is paused. - */ - function _requireNotPaused() internal view virtual { - require(!paused(), "Pausable: paused"); - } - - /** - * @dev Throws if the contract is not paused. - */ - function _requirePaused() internal view virtual { - require(paused(), "Pausable: not paused"); - } - - /** - * @dev Triggers stopped state. - * - * Requirements: - * - * - The contract must not be paused. - */ - function _pause() internal virtual whenNotPaused { - _paused = true; - emit Paused(_msgSender()); - } - - /** - * @dev Returns to normal state. - * - * Requirements: - * - * - The contract must be paused. - */ - function _unpause() internal virtual whenPaused { - _paused = false; - emit Unpaused(_msgSender()); - } -} - // File contracts/mapping-token/v3/base/xTokenBridgeBase.sol // License-Identifier: MIT diff --git a/helix-contract/test/6_test_xtoken_v3.js b/helix-contract/test/6_test_xtoken_v3.js index 6baa648..471fbce 100644 --- a/helix-contract/test/6_test_xtoken_v3.js +++ b/helix-contract/test/6_test_xtoken_v3.js @@ -38,7 +38,7 @@ describe("xtoken tests", () => { console.log("mock msgline deployed address:", mockBackingMsgline.address, mockIssuingMsgline.address); // deploy msgline messager - const msglineMessagerContract = await ethers.getContractFactory("MsglineMessager"); + const msglineMessagerContract = await ethers.getContractFactory("MsgportMessager"); const backingMessager = await msglineMessagerContract.deploy(dao, mockBackingMsgline.address); await backingMessager.deployed(); console.log("backing messager deployed address:", backingMessager.address); @@ -89,11 +89,11 @@ describe("xtoken tests", () => { }); const guardBackingContract = await ethers.getContractFactory("GuardV3"); - const backingGuard = await guardBackingContract.deploy([guards[0].address, guards[1].address, guards[2].address], 2, 60); + const backingGuard = await guardBackingContract.deploy([guards[0].address, guards[1].address, guards[2].address], owner.address, 2, 60); await backingGuard.deployed(); await backingGuard.setDepositor(backing.address, true); const guardIssuingContract = await ethers.getContractFactory("GuardV3"); - const issuingGuard = await guardIssuingContract.deploy([guards[0].address, guards[1].address, guards[2].address], 2, 60); + const issuingGuard = await guardIssuingContract.deploy([guards[0].address, guards[1].address, guards[2].address], owner.address, 2, 60); await issuingGuard.deployed(); await issuingGuard.setDepositor(issuing.address, true); @@ -355,6 +355,42 @@ describe("xtoken tests", () => { expect(balanceRecipientAfter.sub(balanceRecipientBefore)).to.equal(amount); } + async function guardSetClaimTime( + guard, + timestamp, + wallets + ) { + // encode value + const nonce = await guard.nonce(); + console.log(nonce); + const structHash = + ethUtil.keccak256( + abi.rawEncode( + ['bytes4', 'bytes', 'uint256'], + [abi.methodID('setMaxUnclaimableTime', ['uint256', 'bytes[]' ]), + abi.rawEncode(['uint256'], [timestamp]), + Number(nonce) + ] + ) + ); + const dataHash = await guard.encodeDataHash(structHash); + const signatures = wallets.map((wallet) => { + const address = wallet.address; + const privateKey = ethers.utils.arrayify(wallet.privateKey); + const signatureECDSA = secp256k1.ecdsaSign(ethers.utils.arrayify(dataHash), privateKey); + const ethRecID = signatureECDSA.recid + 27; + const signature = Uint8Array.from( + signatureECDSA.signature.join().split(',').concat(ethRecID) + ); + return ethers.utils.hexlify(signature); + }); + const timeBefore = await guard.maxUnclaimableTime(); + expect((timeBefore.sub(timestamp)).lt(0)); + await guard.setMaxUnclaimableTime(timestamp, signatures); + const timeAfter = await guard.maxUnclaimableTime(); + expect(timeAfter).to.equal(timestamp); + } + await registerToken( nativeTokenAddress, "ethereum", @@ -545,6 +581,8 @@ describe("xtoken tests", () => { true, false ); + + await guardSetClaimTime(issuingGuard, 110011, [guards[0], guards[1]]); }); });