From cf3c083fbe6e20ee676b338aa1a9b7aa24806f26 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Tue, 17 Oct 2023 15:58:01 +0800 Subject: [PATCH] refresh flatten file --- helix-contract/deploy/deploy_ln_create2.js | 44 + helix-contract/deploy/deploy_ln_logic.js | 4 +- helix-contract/deploy/flatten-ln.sh | 2 + .../flatten/arbi2eth/LnArbitrumL1Issuing.sol | 2293 --------- .../flatten/arbi2eth/LnArbitrumL2Backing.sol | 1882 ------- helix-contract/flatten/lnv2/Arb2EthSource.sol | 2056 -------- helix-contract/flatten/lnv2/Arb2EthTarget.sol | 2483 --------- .../flatten/lnv2/Eth2ArbReceiveService.sol | 147 + .../flatten/lnv2/Eth2ArbSendService.sol | 693 +++ helix-contract/flatten/lnv2/Eth2ArbSource.sol | 2646 ---------- helix-contract/flatten/lnv2/Eth2ArbTarget.sol | 1923 ------- .../flatten/lnv2/Eth2LineaReceiveService.sol | 24 +- .../flatten/lnv2/Eth2LineaSendService.sol | 34 +- .../flatten/lnv2/Eth2LineaSource.sol | 2059 -------- .../flatten/lnv2/Eth2LineaTarget.sol | 1897 ------- .../flatten/lnv2/Eth2ZkSyncSource.sol | 2091 -------- .../flatten/lnv2/Eth2ZkSyncTarget.sol | 1894 ------- .../flatten/lnv2/LayerZeroBridge.sol | 2388 --------- .../flatten/lnv2/LayerZeroMessager.sol | 34 +- .../flatten/lnv2/Linea2EthSource.sol | 2031 -------- .../flatten/lnv2/Linea2EthTarget.sol | 1897 ------- .../flatten/lnv2/LnBridgeBaseLZ.sol | 2388 --------- .../flatten/lnv2/LnDefaultBridge.sol | 487 +- .../flatten/lnv2/LnOppositeBridge.sol | 7 +- helix-contract/flatten/lnv2/TestToken.sol | 170 +- .../flatten/lnv2/ZkSync2EthSource.sol | 2025 -------- .../flatten/lnv2/ZkSync2EthTarget.sol | 1931 ------- helix-contract/flatten/lnv2/debugMessager.sol | 6 +- helix-contract/flatten/lp/LpSub2EthBridge.sol | 1992 -------- helix-contract/flatten/lp/LpSub2SubBridge.sol | 2002 -------- .../DarwiniaSub2EthMessageEndpoint.sol | 1324 ----- helix-contract/flatten/sub2eth/Erc20.sol | 555 -- .../flatten/sub2eth/Erc20Sub2EthBacking.sol | 2105 -------- .../Erc20Sub2EthMappingTokenFactory.sol | 2593 ---------- helix-contract/flatten/sub2eth/Guard.sol | 1207 ----- helix-contract/flatten/sub2eth/ProxyAdmin.sol | 985 ---- .../sub2eth/TransparentUpgradeableProxy.sol | 798 --- helix-contract/flatten/sub2eth/WToken.sol | 92 - .../DarwiniaSub2SubMessageEndpoint.sol | 4547 ----------------- helix-contract/flatten/sub2sub/Erc20.sol | 555 -- .../flatten/sub2sub/Erc20Sub2SubBacking.sol | 2181 -------- .../Erc20Sub2SubMappingTokenFactory.sol | 2662 ---------- helix-contract/flatten/sub2sub/Guard.sol | 1207 ----- helix-contract/flatten/sub2sub/WToken.sol | 92 - helix-contract/hardhat.config.js | 2 +- 45 files changed, 1268 insertions(+), 59167 deletions(-) create mode 100644 helix-contract/deploy/deploy_ln_create2.js delete mode 100644 helix-contract/flatten/arbi2eth/LnArbitrumL1Issuing.sol delete mode 100644 helix-contract/flatten/arbi2eth/LnArbitrumL2Backing.sol delete mode 100644 helix-contract/flatten/lnv2/Arb2EthSource.sol delete mode 100644 helix-contract/flatten/lnv2/Arb2EthTarget.sol create mode 100644 helix-contract/flatten/lnv2/Eth2ArbReceiveService.sol create mode 100644 helix-contract/flatten/lnv2/Eth2ArbSendService.sol delete mode 100644 helix-contract/flatten/lnv2/Eth2ArbSource.sol delete mode 100644 helix-contract/flatten/lnv2/Eth2ArbTarget.sol delete mode 100644 helix-contract/flatten/lnv2/Eth2LineaSource.sol delete mode 100644 helix-contract/flatten/lnv2/Eth2LineaTarget.sol delete mode 100644 helix-contract/flatten/lnv2/Eth2ZkSyncSource.sol delete mode 100644 helix-contract/flatten/lnv2/Eth2ZkSyncTarget.sol delete mode 100644 helix-contract/flatten/lnv2/LayerZeroBridge.sol delete mode 100644 helix-contract/flatten/lnv2/Linea2EthSource.sol delete mode 100644 helix-contract/flatten/lnv2/Linea2EthTarget.sol delete mode 100644 helix-contract/flatten/lnv2/LnBridgeBaseLZ.sol delete mode 100644 helix-contract/flatten/lnv2/ZkSync2EthSource.sol delete mode 100644 helix-contract/flatten/lnv2/ZkSync2EthTarget.sol delete mode 100644 helix-contract/flatten/lp/LpSub2EthBridge.sol delete mode 100644 helix-contract/flatten/lp/LpSub2SubBridge.sol delete mode 100644 helix-contract/flatten/sub2eth/DarwiniaSub2EthMessageEndpoint.sol delete mode 100644 helix-contract/flatten/sub2eth/Erc20.sol delete mode 100644 helix-contract/flatten/sub2eth/Erc20Sub2EthBacking.sol delete mode 100644 helix-contract/flatten/sub2eth/Erc20Sub2EthMappingTokenFactory.sol delete mode 100644 helix-contract/flatten/sub2eth/Guard.sol delete mode 100644 helix-contract/flatten/sub2eth/ProxyAdmin.sol delete mode 100644 helix-contract/flatten/sub2eth/TransparentUpgradeableProxy.sol delete mode 100644 helix-contract/flatten/sub2eth/WToken.sol delete mode 100644 helix-contract/flatten/sub2sub/DarwiniaSub2SubMessageEndpoint.sol delete mode 100644 helix-contract/flatten/sub2sub/Erc20.sol delete mode 100644 helix-contract/flatten/sub2sub/Erc20Sub2SubBacking.sol delete mode 100644 helix-contract/flatten/sub2sub/Erc20Sub2SubMappingTokenFactory.sol delete mode 100644 helix-contract/flatten/sub2sub/Guard.sol delete mode 100644 helix-contract/flatten/sub2sub/WToken.sol diff --git a/helix-contract/deploy/deploy_ln_create2.js b/helix-contract/deploy/deploy_ln_create2.js new file mode 100644 index 00000000..e30ccbc9 --- /dev/null +++ b/helix-contract/deploy/deploy_ln_create2.js @@ -0,0 +1,44 @@ +const ethUtil = require('ethereumjs-util'); +const abi = require('ethereumjs-abi'); +const secp256k1 = require('secp256k1'); + +var Create2 = require("./create2.js"); + +const privateKey = process.env.PRIKEY + +function wallet(url) { + const provider = new ethers.providers.JsonRpcProvider(url); + const wallet = new ethers.Wallet(privateKey, provider); + return wallet; +} + +async function deployCreate2Deployer(networkUrl, version) { + const salt = ethers.utils.hexZeroPad(ethers.utils.hexlify(ethers.utils.toUtf8Bytes(version)), 32); + const create2Contract = await ethers.getContractFactory("Create2Deployer", wallet); + const bytecode = Create2.getDeployedBytecode(create2Contract, [], []); + const w = wallet(networkUrl); + const unsignedTransaction = { + from: w.address, + to: "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7", + data: `${salt}${bytecode.slice(2)}` + }; + const tx = await w.sendTransaction(unsignedTransaction); + console.log(`deploy create2 tx: ${tx.hash}, salt: ${salt}`); + return; +} + +// 2. deploy mapping token factory +async function main() { + //await deployCreate2Deployer('https://rpc.ankr.com/eth_goerli', 'v1.0.0'); + //await deployCreate2Deployer('https://goerli-rollup.arbitrum.io/rpc', 'v1.0.0'); + await deployCreate2Deployer('https://rpc.testnet.mantle.xyz', 'v1.0.0'); + await deployCreate2Deployer('https://rpc.goerli.linea.build', 'v1.0.0'); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); + diff --git a/helix-contract/deploy/deploy_ln_logic.js b/helix-contract/deploy/deploy_ln_logic.js index c17d3fb5..96be6e5f 100644 --- a/helix-contract/deploy/deploy_ln_logic.js +++ b/helix-contract/deploy/deploy_ln_logic.js @@ -53,8 +53,8 @@ async function main() { const networks = [goerliNetwork, mantleNetwork, arbitrumNetwork, lineaNetwork]; for (const network of networks) { const w = wallet(network.url); - //const logicAddress = await deployLnDefaultBridge(w, network.deployer, "ln-default-logic-v1.1.0"); - const logicAddress = await deployLnOppositeBridge(w, network.deployer, "ln-opposite-logic-v1.1.0"); + //const logicAddress = await deployLnDefaultBridge(w, network.deployer, "ln-default-logic-v1.0.0"); + const logicAddress = await deployLnOppositeBridge(w, network.deployer, "ln-opposite-logic-v1.0.0"); console.log("finish to deploy logic contract, network is: ", network.url); } return; diff --git a/helix-contract/deploy/flatten-ln.sh b/helix-contract/deploy/flatten-ln.sh index 0c002fbd..47550d25 100644 --- a/helix-contract/deploy/flatten-ln.sh +++ b/helix-contract/deploy/flatten-ln.sh @@ -4,6 +4,8 @@ yarn flat contracts/ln/LnDefaultBridge.sol --output $path/LnDefaultBridge.sol yarn flat contracts/ln/LnOppositeBridge.sol --output $path/LnOppositeBridge.sol yarn flat contracts/ln/messager/Eth2LineaSendService.sol --output $path/Eth2LineaSendService.sol yarn flat contracts/ln/messager/Eth2LineaReceiveService.sol --output $path/Eth2LineaReceiveService.sol +yarn flat contracts/ln/messager/Eth2ArbSendService.sol --output $path/Eth2ArbSendService.sol +yarn flat contracts/ln/messager/Eth2ArbReceiveService.sol --output $path/Eth2ArbReceiveService.sol yarn flat contracts/ln/messager/LayerZeroMessager.sol --output $path/LayerZeroMessager.sol yarn flat contracts/ln/messager/debugMessager.sol --output $path/debugMessager.sol yarn flat contracts/ln/test/TestToken.sol --output $path/TestToken.sol diff --git a/helix-contract/flatten/arbi2eth/LnArbitrumL1Issuing.sol b/helix-contract/flatten/arbi2eth/LnArbitrumL1Issuing.sol deleted file mode 100644 index c3ccc319..00000000 --- a/helix-contract/flatten/arbi2eth/LnArbitrumL1Issuing.sol +++ /dev/null @@ -1,2293 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 3/14/2023 - **/ - -pragma solidity ^0.8.10; - -// 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/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/lp/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File contracts/mapping-token/v2/lp/interface/ILnBridgeBacking.sol -// License-Identifier: MIT - - -interface ILnBridgeBacking { - function withdrawLiquidity(bytes32[] memory hashes, bool withdrawNative, address liquidityProvider) external; -} - -// 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/mapping-token/v2/lp/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - 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))), "lpBridgeHelper: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))), "lpBridgeHelper:transferFrom token failed"); - } -} - -// File contracts/mapping-token/v2/lp/base/LnBridgeIssuing.sol -// License-Identifier: MIT - - -contract LnBridgeIssuing is LnBridgeHelper { - mapping(bytes32 => address) public issuedMessages; - - event TransferRelayed(bytes32 transferId, address relayer); - - function relay( - uint256 nonce, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId, - bool issuingNative - ) payable external { - bytes32 transferId = keccak256(abi.encodePacked(nonce, issuingNative, token, sender, receiver, amount, sourceChainId, uint64(block.chainid))); - require(issuedMessages[transferId] == address(0), "lpBridgeIssuing:message exist"); - issuedMessages[transferId] = msg.sender; - if (issuingNative) { - require(msg.value == amount, "lpBridgeIssuing:invalid amount"); - payable(receiver).transfer(amount); - } else { - _safeTransferFrom(token, msg.sender, receiver, uint256(amount)); - } - emit TransferRelayed(transferId, msg.sender); - } - - // only lpProvider can request withdraw liquidity - function _encodeWithdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver) public view returns(bytes memory) { - for (uint idx = 0; idx < transferIds.length; idx++) { - address lpProvider = issuedMessages[transferIds[idx]]; - require(lpProvider == msg.sender, "invalid lpProvider"); - } - return abi.encodeWithSelector(ILnBridgeBacking.withdrawLiquidity.selector, transferIds, withdrawNative, receiver); - } - - // we only allowed token sender or receiver cancel the transaction - function _cancelIssuing( - uint256 nonce, - bool issuingNative, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId - ) internal returns(bytes32 transferId) { - require(sender == msg.sender || receiver == msg.sender, "lpBridgeIssuing:only sender or receiver allowed"); - transferId = keccak256(abi.encodePacked(nonce, issuingNative, token, sender, receiver, amount, sourceChainId, uint64(block.chainid))); - if (issuedMessages[transferId] == msg.sender) { - return transferId; - } - require(issuedMessages[transferId] == address(0), "lpBridgeIssuing:message exist"); - issuedMessages[transferId] = msg.sender; - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File @arbitrum/nitro-contracts/src/bridge/IOwnable.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.4.21 <0.9.0; - -interface IOwnable { - function owner() external view returns (address); -} - -// File @arbitrum/nitro-contracts/src/bridge/IBridge.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IBridge { - event MessageDelivered( - uint256 indexed messageIndex, - bytes32 indexed beforeInboxAcc, - address inbox, - uint8 kind, - address sender, - bytes32 messageDataHash, - uint256 baseFeeL1, - uint64 timestamp - ); - - event BridgeCallTriggered( - address indexed outbox, - address indexed to, - uint256 value, - bytes data - ); - - event InboxToggle(address indexed inbox, bool enabled); - - event OutboxToggle(address indexed outbox, bool enabled); - - event SequencerInboxUpdated(address newSequencerInbox); - - function allowedDelayedInboxList(uint256) external returns (address); - - function allowedOutboxList(uint256) external returns (address); - - /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. - function delayedInboxAccs(uint256) external view returns (bytes32); - - /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. - function sequencerInboxAccs(uint256) external view returns (bytes32); - - function rollup() external view returns (IOwnable); - - function sequencerInbox() external view returns (address); - - function activeOutbox() external view returns (address); - - function allowedDelayedInboxes(address inbox) external view returns (bool); - - function allowedOutboxes(address outbox) external view returns (bool); - - function sequencerReportedSubMessageCount() external view returns (uint256); - - /** - * @dev Enqueue a message in the delayed inbox accumulator. - * These messages are later sequenced in the SequencerInbox, either - * by the sequencer as part of a normal batch, or by force inclusion. - */ - function enqueueDelayedMessage( - uint8 kind, - address sender, - bytes32 messageDataHash - ) external payable returns (uint256); - - function executeCall( - address to, - uint256 value, - bytes calldata data - ) external returns (bool success, bytes memory returnData); - - function delayedMessageCount() external view returns (uint256); - - function sequencerMessageCount() external view returns (uint256); - - // ---------- onlySequencerInbox functions ---------- - - function enqueueSequencerMessage( - bytes32 dataHash, - uint256 afterDelayedMessagesRead, - uint256 prevMessageCount, - uint256 newMessageCount - ) - external - returns ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 acc - ); - - /** - * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type - * This is done through a separate function entrypoint instead of allowing the sequencer inbox - * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either - * every delayed inbox or every sequencer inbox call. - */ - function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) - external - returns (uint256 msgNum); - - // ---------- onlyRollupOrOwner functions ---------- - - function setSequencerInbox(address _sequencerInbox) external; - - function setDelayedInbox(address inbox, bool enabled) external; - - function setOutbox(address inbox, bool enabled) external; - - // ---------- initializer ---------- - - function initialize(IOwnable rollup_) external; -} - -// File @arbitrum/nitro-contracts/src/bridge/IDelayedMessageProvider.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IDelayedMessageProvider { - /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator - event InboxMessageDelivered(uint256 indexed messageNum, bytes data); - - /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator - /// same as InboxMessageDelivered but the batch data is available in tx.input - event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); -} - -// File @arbitrum/nitro-contracts/src/libraries/IGasRefunder.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IGasRefunder { - function onGasSpent( - address payable spender, - uint256 gasUsed, - uint256 calldataSize - ) external returns (bool success); -} - -abstract contract GasRefundEnabled { - /// @dev this refunds the sender for execution costs of the tx - /// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging - /// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded - modifier refundsGas(IGasRefunder gasRefunder) { - uint256 startGasLeft = gasleft(); - _; - if (address(gasRefunder) != address(0)) { - uint256 calldataSize; - assembly { - calldataSize := calldatasize() - } - uint256 calldataWords = (calldataSize + 31) / 32; - // account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost - startGasLeft += calldataWords * 6 + (calldataWords**2) / 512; - // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call - // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input - // solhint-disable-next-line avoid-tx-origin - if (msg.sender != tx.origin) { - // We can't be sure if this calldata came from the top level tx, - // so to be safe we tell the gas refunder there was no calldata. - calldataSize = 0; - } - gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize); - } - } -} - -// File @arbitrum/nitro-contracts/src/bridge/ISequencerInbox.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; -pragma experimental ABIEncoderV2; - - - -interface ISequencerInbox is IDelayedMessageProvider { - struct MaxTimeVariation { - uint256 delayBlocks; - uint256 futureBlocks; - uint256 delaySeconds; - uint256 futureSeconds; - } - - struct TimeBounds { - uint64 minTimestamp; - uint64 maxTimestamp; - uint64 minBlockNumber; - uint64 maxBlockNumber; - } - - enum BatchDataLocation { - TxInput, - SeparateBatchEvent, - NoData - } - - event SequencerBatchDelivered( - uint256 indexed batchSequenceNumber, - bytes32 indexed beforeAcc, - bytes32 indexed afterAcc, - bytes32 delayedAcc, - uint256 afterDelayedMessagesRead, - TimeBounds timeBounds, - BatchDataLocation dataLocation - ); - - event OwnerFunctionCalled(uint256 indexed id); - - /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input - event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data); - - /// @dev a valid keyset was added - event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes); - - /// @dev a keyset was invalidated - event InvalidateKeyset(bytes32 indexed keysetHash); - - function totalDelayedMessagesRead() external view returns (uint256); - - function bridge() external view returns (IBridge); - - /// @dev The size of the batch header - // solhint-disable-next-line func-name-mixedcase - function HEADER_LENGTH() external view returns (uint256); - - /// @dev If the first batch data byte after the header has this bit set, - /// the sequencer inbox has authenticated the data. Currently not used. - // solhint-disable-next-line func-name-mixedcase - function DATA_AUTHENTICATED_FLAG() external view returns (bytes1); - - function rollup() external view returns (IOwnable); - - function isBatchPoster(address) external view returns (bool); - - struct DasKeySetInfo { - bool isValidKeyset; - uint64 creationBlock; - } - - // https://github.com/ethereum/solidity/issues/11826 - // function maxTimeVariation() external view returns (MaxTimeVariation calldata); - // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata); - - /// @notice Remove force inclusion delay after a L1 chainId fork - function removeDelayAfterFork() external; - - /// @notice Force messages from the delayed inbox to be included in the chain - /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and - /// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these - /// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages. - /// @param _totalDelayedMessagesRead The total number of messages to read up to - /// @param kind The kind of the last message to be included - /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included - /// @param baseFeeL1 The l1 gas price of the last message to be included - /// @param sender The sender of the last message to be included - /// @param messageDataHash The messageDataHash of the last message to be included - function forceInclusion( - uint256 _totalDelayedMessagesRead, - uint8 kind, - uint64[2] calldata l1BlockAndTime, - uint256 baseFeeL1, - address sender, - bytes32 messageDataHash - ) external; - - function inboxAccs(uint256 index) external view returns (bytes32); - - function batchCount() external view returns (uint256); - - function isValidKeysetHash(bytes32 ksHash) external view returns (bool); - - /// @notice the creation block is intended to still be available after a keyset is deleted - function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256); - - // ---------- BatchPoster functions ---------- - - function addSequencerL2BatchFromOrigin( - uint256 sequenceNumber, - bytes calldata data, - uint256 afterDelayedMessagesRead, - IGasRefunder gasRefunder - ) external; - - function addSequencerL2Batch( - uint256 sequenceNumber, - bytes calldata data, - uint256 afterDelayedMessagesRead, - IGasRefunder gasRefunder, - uint256 prevMessageCount, - uint256 newMessageCount - ) external; - - // ---------- onlyRollupOrOwner functions ---------- - - /** - * @notice Set max delay for sequencer inbox - * @param maxTimeVariation_ the maximum time variation parameters - */ - function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external; - - /** - * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox - * @param addr the address - * @param isBatchPoster_ if the specified address should be authorized as a batch poster - */ - function setIsBatchPoster(address addr, bool isBatchPoster_) external; - - /** - * @notice Makes Data Availability Service keyset valid - * @param keysetBytes bytes of the serialized keyset - */ - function setValidKeyset(bytes calldata keysetBytes) external; - - /** - * @notice Invalidates a Data Availability Service keyset - * @param ksHash hash of the keyset - */ - function invalidateKeysetHash(bytes32 ksHash) external; - - // ---------- initializer ---------- - - function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external; -} - -// File @arbitrum/nitro-contracts/src/bridge/IInbox.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - - - -interface IInbox is IDelayedMessageProvider { - function bridge() external view returns (IBridge); - - function sequencerInbox() external view returns (ISequencerInbox); - - /** - * @notice Send a generic L2 message to the chain - * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input - * This method will be disabled upon L1 fork to prevent replay attacks on L2 - * @param messageData Data of the message being sent - */ - function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256); - - /** - * @notice Send a generic L2 message to the chain - * @dev This method can be used to send any type of message that doesn't require L1 validation - * This method will be disabled upon L1 fork to prevent replay attacks on L2 - * @param messageData Data of the message being sent - */ - function sendL2Message(bytes calldata messageData) external returns (uint256); - - function sendL1FundedUnsignedTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - bytes calldata data - ) external payable returns (uint256); - - function sendL1FundedContractTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - address to, - bytes calldata data - ) external payable returns (uint256); - - function sendUnsignedTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - function sendContractTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - /** - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendL1FundedUnsignedTransactionToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - bytes calldata data - ) external payable returns (uint256); - - /** - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendUnsignedTransactionToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - /** - * @notice Send a message to initiate L2 withdrawal - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendWithdrawEthToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - uint256 value, - address withdrawTo - ) external returns (uint256); - - /** - * @notice Get the L1 fee for submitting a retryable - * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value - * @dev This formula may change in the future, to future proof your code query this method instead of inlining!! - * @param dataLength The length of the retryable's calldata, in bytes - * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used - */ - function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) - external - view - returns (uint256); - - /** - * @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract - * @dev This does not trigger the fallback function when receiving in the L2 side. - * Look into retryable tickets if you are interested in this functionality. - * @dev This function should not be called inside contract constructors - */ - function depositEth() external payable returns (uint256); - - /** - * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts - * @dev all msg.value will deposited to callValueRefundAddress on L2 - * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error - * @param to destination L2 contract address - * @param l2CallValue call value for retryable L2 message - * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance - * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled - * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param data ABI encoded data of L2 message - * @return unique message number of the retryable transaction - */ - function createRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); - - /** - * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts - * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds - * come from the deposit alone, rather than falling back on the user's L2 balance - * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). - * createRetryableTicket method is the recommended standard. - * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error - * @param to destination L2 contract address - * @param l2CallValue call value for retryable L2 message - * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance - * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled - * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param data ABI encoded data of L2 message - * @return unique message number of the retryable transaction - */ - function unsafeCreateRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); - - // ---------- onlyRollupOrOwner functions ---------- - - /// @notice pauses all inbox functionality - function pause() external; - - /// @notice unpauses all inbox functionality - function unpause() external; - - // ---------- initializer ---------- - - /** - * @dev function to be called one time during the inbox upgrade process - * this is used to fix the storage slots - */ - function postUpgradeInit(IBridge _bridge) external; - - function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external; -} - -// File contracts/mapping-token/v2/lp/LnArbitrumL1Issuing.sol -// License-Identifier: MIT - - - - -contract LnArbitrumL1Issuing is Initializable, LnAccessController, LnBridgeIssuing { - IInbox public inbox; - address public remoteBacking; - - event TransferCanceled(bytes32 transferId, address sender); - - receive() external payable {} - - function initialize(address _dao, address _inbox) public initializer { - inbox = IInbox(_inbox); - _initialize(_dao); - } - - function setRemoteBacking(address _remoteBacking) external onlyDao { - remoteBacking = _remoteBacking; - } - - function submissionFee( - uint256 baseFee, - bytes32[] memory transferIds, - bool withdrawNative, - address receiver, - uint256 percentIncrease - ) external view returns(uint256) { - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, receiver); - uint256 fee = IInbox(inbox).calculateRetryableSubmissionFee(withdrawCall.length, baseFee); - return fee + fee * percentIncrease / 100; - } - - function requestWithdrawLiquidity( - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid, - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) payable external whenNotPaused { - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, receiver); - _sendMessage( - maxSubmissionCost, - maxGas, - gasPriceBid, - withdrawCall, - msg.value); - } - - function _sendMessage( - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid, - bytes memory message, - uint256 prepaid - ) internal returns(uint256) { - return inbox.createRetryableTicket{ value: prepaid }( - remoteBacking, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - message - ); - } - - function requestCancelIssuing( - uint256 nonce, - bool issuingNative, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId, - bool withdrawNative, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) payable external whenNotPaused { - bytes32 transferId = _cancelIssuing(nonce, issuingNative, token, sender, receiver, amount, sourceChainId); - bytes32[] memory transferIds = new bytes32[](1); - transferIds[0] = transferId; - // return token to the source sender - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, sender); - _sendMessage(maxSubmissionCost, maxGas, gasPriceBid, withdrawCall, msg.value); - emit TransferCanceled(transferId, msg.sender); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/arbi2eth/LnArbitrumL2Backing.sol b/helix-contract/flatten/arbi2eth/LnArbitrumL2Backing.sol deleted file mode 100644 index bdc9fe31..00000000 --- a/helix-contract/flatten/arbi2eth/LnArbitrumL2Backing.sol +++ /dev/null @@ -1,1882 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 3/14/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/lp/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/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/mapping-token/v2/lp/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - 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))), "lpBridgeHelper: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))), "lpBridgeHelper:transferFrom token failed"); - } -} - -// File contracts/mapping-token/v2/lp/base/LnBridgeBacking.sol -// License-Identifier: MIT - - - -/// @title LnBridgeBacking -/// @notice LnBridgeBacking is a contract to help user lock token and then trigger remote chain issuing -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnBridgeBacking is LnBridgeHelper { - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - uint32 constant public INVALID_TOKEN_INDEX = type(uint32).max; - // the registered token info - // localToken and remoteToken is the pair of erc20 token addresses - // helixFee is charged by system, if it's bigger then half of user's fee, descrease it to the half - // remoteChainId is the remote block.chainid - // remoteIsNative is true when the remoteToken is the remote wrapped native token - struct TokenInfo { - address localToken; - address remoteToken; - uint112 helixFee; - uint64 remoteChainId; - uint8 localDecimals; - uint8 remoteDecimals; - bool remoteIsNative; - } - // registered token info - TokenInfo[] public tokens; - // each time cross chain transfer, amount and fee can't be larger than type(uint112).max - struct LockInfo { - uint32 tokenIndex; - uint112 amount; - uint112 fee; - } - mapping(bytes32 => LockInfo) public lockInfos; - address public feeReceiver; - uint32 public wTokenIndex = INVALID_TOKEN_INDEX; - - event TokenLocked( - uint64 toChainId, - bool isNative, - bool issuingNative, - uint256 nonce, - bytes32 transferId, - address token, - uint112 amount, - uint112 fee, - address receiver); - event FeeUpdated(bytes32 transferId, uint256 fee); - event LiquidityWithdrawn(bytes32 transferId, address receiver); - - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "lpBridgeBacking:invalid helix fee receiver"); - feeReceiver = _feeReceiver; - } - - function _updateHelixFee(uint32 _tokenIndex, uint112 _helixFee) internal { - require(_tokenIndex < tokens.length, "lpBridgeBacking:invalid token index"); - tokens[_tokenIndex].helixFee = _helixFee; - } - - function _setwTokenIndex(uint32 _wTokenIndex) internal { - wTokenIndex = _wTokenIndex; - } - - function _registerToken( - address localToken, - address remoteToken, - uint112 helixFee, - uint64 remoteChainId, - uint8 localDecimals, - uint8 remoteDecimals, - bool remoteIsNative - ) internal { - tokens.push(TokenInfo(localToken, remoteToken, helixFee, remoteChainId, localDecimals, remoteDecimals, remoteIsNative)); - } - - function _lockAndRemoteIssuing( - bool lockNative, - uint256 nonce, - uint32 tokenIndex, - uint112 amount, - uint112 fee, - address receiver, - bool issuingNative - ) internal returns(TokenInfo memory tokenInfo) { - tokenInfo = tokens[tokenIndex]; - require(fee > tokenInfo.helixFee && amount > 0, "lpBridgeBacking:fee or amount is not enough"); - require(!issuingNative || tokenInfo.remoteIsNative, "lpBridgeBacking:remote not native"); - uint256 remoteAmount = uint256(amount) * 10**tokenInfo.remoteDecimals / 10**tokenInfo.localDecimals; - require(remoteAmount < MAX_TRANSFER_AMOUNT, "lpBridgeBacking:overflow amount"); - bytes32 transferId = keccak256(abi.encodePacked( - nonce, - issuingNative, - tokenInfo.remoteToken, - msg.sender, - receiver, - uint112(remoteAmount), - uint64(block.chainid), - tokenInfo.remoteChainId)); - require(lockInfos[transferId].amount == 0, "lpBridgeBacking:transferId exist"); - lockInfos[transferId] = LockInfo(tokenIndex, amount, fee); - emit TokenLocked(tokenInfo.remoteChainId, lockNative, issuingNative, nonce, transferId, tokenInfo.localToken, amount, fee, receiver); - } - - function lockAndRemoteIssuing( - uint256 nonce, - address receiver, - uint112 amount, - uint112 fee, - uint32 tokenIndex, - bool issuingNative - ) external { - require(tokens.length > tokenIndex, "lpBridgeBacking:token not registered"); - TokenInfo memory info = _lockAndRemoteIssuing(false, nonce, tokenIndex, amount, fee, receiver, issuingNative); - _safeTransferFrom(info.localToken, msg.sender, address(this), amount + fee); - } - - function lockNativeAndRemoteIssuing( - uint112 amount, - uint112 fee, - address receiver, - uint256 nonce, - bool issuingNative - ) external payable { - require(amount + fee == msg.value, "lpBridgeBacking:amount unmatched"); - require(wTokenIndex != INVALID_TOKEN_INDEX, "lpBridgeBacking:not support"); - TokenInfo memory info = _lockAndRemoteIssuing(true, nonce, wTokenIndex, amount, fee, receiver, issuingNative); - IWToken(info.localToken).deposit{value: amount + fee}(); - } - - function _increaseFee(bytes32 transferId, uint256 fee) internal returns(uint32 tokenIndex) { - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.amount > 0 && lockInfo.tokenIndex < tokens.length, "lpBridgeBacking:invalid transferId"); - uint256 newFee = lockInfo.fee + fee; - require(newFee < MAX_TRANSFER_AMOUNT, "lpBridgeBacking:fee too large"); - lockInfos[transferId].fee = uint112(newFee); - tokenIndex = lockInfo.tokenIndex; - emit FeeUpdated(transferId, newFee); - } - - function increaseFee(bytes32 transferId, uint256 fee) external { - uint32 tokenIndex = _increaseFee(transferId, fee); - TokenInfo memory tokenInfo = tokens[tokenIndex]; - _safeTransferFrom(tokenInfo.localToken, msg.sender, address(this), fee); - } - - function increaseNativeFee(bytes32 transferId) external payable { - uint32 tokenIndex = _increaseFee(transferId, msg.value); - require(tokenIndex == wTokenIndex && wTokenIndex != INVALID_TOKEN_INDEX, "lpBridgeBacking:invalid token index"); - TokenInfo memory tokenInfo = tokens[tokenIndex]; - IWToken(tokenInfo.localToken).deposit{value: msg.value}(); - } - - // we require the same token to withdrawn - function _withdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) internal { - require(transferIds.length > 0, "lpBridgeBacking:invalid transferIds size"); - uint32 tokenIndex = lockInfos[transferIds[0]].tokenIndex; - require(tokenIndex < tokens.length, "lpBridgeBacking:out of token size"); - uint256 amount = 0; - uint256 fee = 0; - for (uint i = 0; i < transferIds.length; i++) { - bytes32 transferId = transferIds[i]; - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.amount > 0 && lockInfo.tokenIndex < tokens.length, "lpBridgeBacking:invalid transferId"); - require(lockInfo.tokenIndex == tokenIndex, "lpBridgeBacking:invalid tokenindex"); - //can't delete lockInfos directly - lockInfos[transferId].tokenIndex = INVALID_TOKEN_INDEX; - amount += lockInfo.amount; - fee += lockInfo.fee; - emit LiquidityWithdrawn(transferId, receiver); - } - TokenInfo memory tokenInfo = tokens[tokenIndex]; - uint256 helixFee = transferIds.length * tokenInfo.helixFee; - if (helixFee > fee / 2) { - helixFee = fee / 2; - } - uint256 lpAmount = amount + fee - helixFee; - if (withdrawNative && tokenIndex == wTokenIndex) { - IWToken(tokenInfo.localToken).withdraw(lpAmount); - payable(receiver).transfer(lpAmount); - } else { - _safeTransfer(tokenInfo.localToken, receiver, lpAmount); - } - _safeTransfer(tokenInfo.localToken, feeReceiver, helixFee); - } - - function tokenLength() external view returns (uint) { - return tokens.length; - } -} - -// File @arbitrum/nitro-contracts/src/libraries/AddressAliasHelper.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - - -library AddressAliasHelper { - uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); - - /// @notice Utility function that converts the address in the L1 that submitted a tx to - /// the inbox to the msg.sender viewed in the L2 - /// @param l1Address the address in the L1 that triggered the tx to L2 - /// @return l2Address L2 address as viewed in msg.sender - function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { - unchecked { - l2Address = address(uint160(l1Address) + OFFSET); - } - } - - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l2Address L2 address as viewed in msg.sender - /// @return l1Address the address in the L1 that triggered the tx to L2 - function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { - unchecked { - l1Address = address(uint160(l2Address) - OFFSET); - } - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/lp/LnArbitrumL2Backing.sol -// License-Identifier: MIT - - - - -contract LnArbitrumL2Backing is Initializable, LnAccessController, LnBridgeBacking { - address public remoteIssuing; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(msg.sender == AddressAliasHelper.applyL1ToL2Alias(remoteIssuing), "LnArbitrumL2Backing:invalid remote caller"); - _; - } - - function initialize(address dao) public initializer { - _initialize(dao); - _setFeeReceiver(dao); - _setwTokenIndex(INVALID_TOKEN_INDEX); - } - - function setwTokenIndex(uint32 _wTokenIndex) external onlyDao { - _setwTokenIndex(_wTokenIndex); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function updateHelixFee(uint32 _tokenIndex, uint112 _helixFee) external onlyDao { - _updateHelixFee(_tokenIndex, _helixFee); - } - - function setRemoteIssuing(address _remoteIssuing) external onlyDao { - remoteIssuing = _remoteIssuing; - } - - // backing mode called - function registerToken( - address local, - address remote, - uint112 helixFee, - uint32 remoteChainId, - uint8 localDecimals, - uint8 remoteDecimals, - bool remoteIsNative - ) external onlyOperator { - _registerToken(local, remote, helixFee, remoteChainId, localDecimals, remoteDecimals, remoteIsNative); - } - - function withdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) external onlyRemoteBridge whenNotPaused { - _withdrawLiquidity(transferIds, withdrawNative, receiver); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Arb2EthSource.sol b/helix-contract/flatten/lnv2/Arb2EthSource.sol deleted file mode 100644 index 8cec442c..00000000 --- a/helix-contract/flatten/lnv2/Arb2EthSource.sol +++ /dev/null @@ -1,2056 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/12/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// 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/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnOppositeBridgeSource.sol -// License-Identifier: MIT - - -/// @title LnBridgeSource -/// @notice LnBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can paid for relayer and slash the transfer, then request slash from lnProvider's margin. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnOppositeBridgeSource is LnBridgeHelper { - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - // the Liquidity Node provider info - // Liquidity Node need register first - struct LnProviderConfigure { - uint112 margin; - uint112 baseFee; - // liquidityFeeRate / 100,000 * amount = liquidityFee - // the max liquidity fee rate is 0.255% - uint8 liquidityFeeRate; - } - struct LnProviderInfo { - LnProviderConfigure config; - bool pause; - bytes32 lastTransferId; - } - - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId updated, revert - // 2. if margin decrease or totalFee increase, revert - // 3. if margin increase or totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 depositedMargin; - uint112 totalFee; - } - // registered token info - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // registered lnProviders - mapping(bytes32=>LnProviderInfo) public lnProviders; - // each time cross chain transfer, amount and fee can't be larger than type(uint112).max - struct LockInfo { - // amount + providerFee + penaltyLnCollateral - // the Indexer should be care about this value, it will frozen lnProvider's margin when the transfer not finished. - // and when the slasher slash success, this amount of token will be transfer from lnProvider's margin to slasher. - uint112 amountWithFeeAndPenalty; - bool hasSlashed; - } - // key: transferId = hash(proviousTransferId, timestamp, targetToken, receiver, targetAmount) - // * `proviousTransferId` is used to ensure the continuous of the transfer - // * `timestamp` is the block.timestmap to judge timeout on target chain(here we support source and target chain has the same world clock) - // * `targetToken`, `receiver` and `targetAmount` are used on target chain to transfer target token. - mapping(bytes32 => LockInfo) public lockInfos; - address public feeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LiquidityWithdrawn(address provider, address token, uint112 amount); - event Slash(bytes32 transferId, address provider, address token, uint112 margin, address slasher); - // relayer - event LnProviderUpdated(address provider, address token, uint112 margin, uint112 baseFee, uint8 liquidityfeeRate); - - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - feeReceiver = _feeReceiver; - } - - function _updateProtocolFee(address _token, uint112 _protocolFee) internal { - require(tokenInfos[_token].isRegistered, "token not registered"); - tokenInfos[_token].protocolFee = _protocolFee; - } - - function _updatePenaltyLnCollateral(address _token, uint112 _penaltyLnCollateral) internal { - require(tokenInfos[_token].isRegistered, "token not registered"); - tokenInfos[_token].penaltyLnCollateral = _penaltyLnCollateral; - } - - function providerPause(address sourceToken) external { - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - lnProviders[providerKey].pause = true; - } - - function providerUnpause(address sourceToken) external { - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - lnProviders[providerKey].pause = false; - } - - // lnProvider can register or update its configure by using this function - // * `margin` is the increased value of the deposited margin - function updateProviderFeeAndMargin( - address sourceToken, - uint112 margin, - uint112 baseFee, - uint8 liquidityFeeRate - ) external payable { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token is not registered"); - - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - - LnProviderConfigure memory config = LnProviderConfigure( - // the margin can be only increased here - margin + providerInfo.config.margin, - baseFee, - liquidityFeeRate - ); - - lnProviders[providerKey].config = config; - - if (sourceToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - if (margin > 0) { - _safeTransferFrom(sourceToken, msg.sender, address(this), margin); - } - } - emit LnProviderUpdated(msg.sender, sourceToken, config.margin, baseFee, liquidityFeeRate); - } - - function _registerToken( - address sourceToken, - address targetToken, - uint112 protocolFee, - uint112 penaltyLnCollateral, - uint8 sourceDecimals, - uint8 targetDecimals - ) internal { - tokenInfos[sourceToken] = TokenInfo( - targetToken, - protocolFee, - penaltyLnCollateral, - sourceDecimals, - targetDecimals, - true - ); - } - - function calculateProviderFee(LnProviderConfigure memory config, uint112 amount) internal pure returns(uint256) { - return uint256(config.baseFee) + uint256(config.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - // providerFee = provider.baseFee + provider.liquidityFeeRate * amount - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - bytes32 providerKey = getProviderKey(provider, sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.config, amount); - return providerFee + tokenInfos[sourceToken].protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, margin) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - bytes32 providerKey = getProviderKey(snapshot.provider, snapshot.sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - - require(!providerInfo.pause, "provider paused"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - - uint256 providerFee = calculateProviderFee(providerInfo.config, amount); - - // Note: this requirement is not enough to ensure that the lnProvider's margin is enough because there maybe some frozen margins in other transfers - require(providerInfo.config.margin >= amount + tokenInfo.penaltyLnCollateral + uint112(providerFee), "amount not valid"); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired"); - require(snapshot.totalFee >= tokenInfo.protocolFee + providerFee, "fee is invalid"); - require(snapshot.depositedMargin <= providerInfo.config.margin, "margin updated"); - - uint256 targetAmount = uint256(amount) * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - uint112(targetAmount))); - require(lockInfos[transferId].amountWithFeeAndPenalty == 0, "transferId exist"); - lockInfos[transferId] = LockInfo(amount + tokenInfo.penaltyLnCollateral + uint112(providerFee), false); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(feeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - feeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - amount, - uint112(providerFee), - timestamp, - receiver); - } - - // this slash is called by remote message - // the token should be sent to the slasher who slash and finish the transfer on target chain. - // latestSlashTransferId is the latest slashed transfer trusted from the target chain, and the current slash transfer cannot be executed before the latestSlash transfer. - // after slash, the margin of lnProvider need to be updated - function _slash( - bytes32 latestSlashTransferId, - bytes32 transferId, - address sourceToken, - address provider, - address slasher - ) internal { - // check lastTransfer - // ensure last slash transfer(checked on target chain) has been slashed - LockInfo memory lastLockInfo = lockInfos[latestSlashTransferId]; - require(lastLockInfo.hasSlashed || latestSlashTransferId == INIT_SLASH_TRANSFER_ID, "latest slash transfer invalid"); - LockInfo memory lockInfo = lockInfos[transferId]; - - // ensure transfer exist and not slashed yet - require(!lockInfo.hasSlashed, "transfer has been slashed"); - require(lockInfo.amountWithFeeAndPenalty > 0, "lnBridgeSource:invalid transferId"); - - bytes32 providerKey = getProviderKey(provider, sourceToken); - - LnProviderInfo memory lnProvider = lnProviders[providerKey]; - lockInfos[transferId].hasSlashed = true; - // transfer token to the slasher - uint256 slashAmount = lockInfo.amountWithFeeAndPenalty; - require(lnProvider.config.margin >= slashAmount, "margin not enough"); - uint112 updatedMargin = lnProvider.config.margin - uint112(slashAmount); - lnProviders[providerKey].config.margin = updatedMargin; - - if (sourceToken == address(0)) { - _safeTransferNative(slasher, slashAmount); - } else { - _safeTransfer(sourceToken, slasher, slashAmount); - } - - emit Slash(transferId, provider, sourceToken, updatedMargin, slasher); - } - - // lastTransfer is the latest slash transfer, all transfer must be relayed or slashed - // if user use the snapshot before this transaction to send cross-chain transfer, it should be reverted because this `_withdrawMargin` will decrease margin. - function _withdrawMargin( - bytes32 latestSlashTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) internal { - // check the latest slash transfer - // ensure latest slash tranfer(verified on target chain) has been slashed on source chain - LockInfo memory lastRefundLockInfo = lockInfos[latestSlashTransferId]; - require(lastRefundLockInfo.hasSlashed || latestSlashTransferId == INIT_SLASH_TRANSFER_ID, "latest slash transfer invalid"); - - // use this condition to ensure that the withdraw message is sent by the provider - // the parameter provider is the message sender of this remote withdraw call - bytes32 providerKey = getProviderKey(provider, sourceToken); - LnProviderInfo memory lnProvider = lnProviders[providerKey]; - - // ensure all transfer has finished - require(lnProvider.lastTransferId == lastTransferId, "invalid last transferid"); - require(lnProvider.config.margin >= amount, "margin not enough"); - uint112 updatedMargin = lnProvider.config.margin - amount; - lnProviders[providerKey].config.margin = updatedMargin; - if (sourceToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(sourceToken, provider, amount); - } - emit LiquidityWithdrawn(provider, sourceToken, updatedMargin); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File @arbitrum/nitro-contracts/src/libraries/AddressAliasHelper.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - - -library AddressAliasHelper { - uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); - - /// @notice Utility function that converts the address in the L1 that submitted a tx to - /// the inbox to the msg.sender viewed in the L2 - /// @param l1Address the address in the L1 that triggered the tx to L2 - /// @return l2Address L2 address as viewed in msg.sender - function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { - unchecked { - l2Address = address(uint160(l1Address) + OFFSET); - } - } - - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l2Address L2 address as viewed in msg.sender - /// @return l1Address the address in the L1 that triggered the tx to L2 - function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { - unchecked { - l1Address = address(uint160(l2Address) - OFFSET); - } - } -} - -// File contracts/ln/Arb2EthSource.sol -// License-Identifier: MIT - - - - -contract Arb2EthSource is Initializable, LnAccessController, LnOppositeBridgeSource { - address public remoteBridge; - address public remoteBridgeAlias; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(msg.sender == remoteBridgeAlias, "invalid remote caller"); - _; - } - - function initialize(address dao) public initializer { - _initialize(dao); - _setFeeReceiver(dao); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function updateProtocolFee(address token, uint112 _protocolFee) external onlyDao { - _updateProtocolFee(token, _protocolFee); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - remoteBridgeAlias = AddressAliasHelper.applyL1ToL2Alias(remoteBridge); - } - - function setRemoteBridgeAlias(address _remoteBridgeAlias) external onlyDao { - remoteBridgeAlias = _remoteBridgeAlias; - } - - function registerToken( - address sourceToken, - address targetToken, - uint112 protocolFee, - uint112 penaltyLnCollateral, - uint8 sourceDecimals, - uint8 targetDecimals - ) external onlyOperator { - _registerToken(sourceToken, targetToken, protocolFee, penaltyLnCollateral, sourceDecimals, targetDecimals); - } - - function slash( - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) external onlyRemoteBridge whenNotPaused { - _slash(latestSlashTransferId, transferId, sourceToken, provider, slasher); - } - - function withdrawMargin( - bytes32 latestSlashTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) external onlyRemoteBridge whenNotPaused { - _withdrawMargin(latestSlashTransferId, lastTransferId, provider, sourceToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Arb2EthTarget.sol b/helix-contract/flatten/lnv2/Arb2EthTarget.sol deleted file mode 100644 index 04de0e04..00000000 --- a/helix-contract/flatten/lnv2/Arb2EthTarget.sol +++ /dev/null @@ -1,2483 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/12/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/ln/interface/ILnOppositeBridgeSource.sol -// License-Identifier: MIT - - -interface ILnOppositeBridgeSource { - function slash( - bytes32 lastRefundTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) external; - - function withdrawMargin( - bytes32 lastRefundTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) external; -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnOppositeBridgeTarget.sol -// License-Identifier: MIT - - -contract LnOppositeBridgeTarget is LnBridgeHelper { - uint256 constant public MIN_REFUND_TIMESTAMP = 30 * 60; - - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - // if there is no slash transfer before, then it's latestSlashTransferId is assigned by INIT_SLASH_TRANSFER_ID, a special flag - struct SlashInfo { - address provider; - address sourceToken; - address slasher; - } - - // transferId => latest slash transfer Id - mapping(bytes32 => bytes32) public fillTransfers; - // transferId => Slash info - mapping(bytes32 => SlashInfo) public slashInfos; - - event TransferFilled(bytes32 transferId, address slasher); - - // if slasher is nonzero, then it's a slash fill transfer - function _checkPreviousAndFillTransfer( - bytes32 transferId, - bytes32 previousTransferId - ) internal { - // the first fill transfer, we fill the INIT_SLASH_TRANSFER_ID as the latest slash transferId - if (previousTransferId == bytes32(0)) { - fillTransfers[transferId] = INIT_SLASH_TRANSFER_ID; - } else { - // Find the previous slash fill, it is a slash fill if the slasher is not zero address. - bytes32 previousLatestSlashTransferId = fillTransfers[previousTransferId]; - require(previousLatestSlashTransferId != bytes32(0), "previous fill not exist"); - - SlashInfo memory previousSlashInfo = slashInfos[previousTransferId]; - // we use latestSlashTransferId to store the latest slash transferId - // if previous.slasher != 0, then previous is slashed - // if previous.slasher == 0, then previous is not slashed - bytes32 latestSlashTransferId = previousSlashInfo.slasher != address(0) ? previousTransferId : previousLatestSlashTransferId; - - fillTransfers[transferId] = latestSlashTransferId; - } - } - - // fill transfer - // 1. if transfer is not slashed or relayed, LnProvider relay message to fill the transfer, and the transfer finished on target chain - // 2. if transfer is timeout and not processed, slasher(any account) can fill the transfer and request slash - // if it's filled by slasher, we store the address of the slasher - // expectedTransferId used to ensure the parameter is the same as on source chain - // some cases - // 1) If transferId is not exist on source chain, it'll be rejected by source chain when shashed. - // 2) If transferId exist on source chain. We have the same hash process on source and target chain, so the previousTransferId is trusted. - // 2.1) If transferId is the first transfer Id of this provider, then previousTransferId is zero and the latestSlashTransferId is INIT_SLASH_TRANSFER_ID - // 2.2) If transferId is not the first transfer, then it's latestSlashTransferId has the next two scenarios - // * the previousTransfer is a slash transfer, then latestSlashTransferId is previousTransferId - // * the previousTransfer is a normal relayed transfer, then latestSlashTransferId is previousTransfer's latestSlashTransferId - // I. transferId is trusted => previousTransferId is trusted => previousTransfer.previousTransferId is trusted => ... => firstTransfer is trusted - // II. transferId is trusted => previousTransferId is trusted => latestSlashTransferId is trusted if previousTransfer is a slash transfer - // III. Both I and II => latestSlashTransferId is trusted if previousTransfer is normal relayed tranfer - function _fillTransfer( - TransferParameter calldata params, - bytes32 expectedTransferId - ) internal { - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount)); - require(expectedTransferId == transferId, "check expected transferId failed"); - // Make sure this transfer was never filled before - require(fillTransfers[transferId] == bytes32(0), "fill exist"); - - _checkPreviousAndFillTransfer(transferId, params.previousTransferId); - - if (params.targetToken == address(0)) { - require(msg.value >= params.amount, "invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external { - // normal relay message, fill slasher as zero - require(params.provider == msg.sender, "invalid provider"); - _fillTransfer(params, expectedTransferId); - - emit TransferFilled(expectedTransferId, address(0)); - } - - // The condition for slash is that the transfer has timed out - // Meanwhile we need to request a slash transaction to the source chain to withdraw the LnProvider's margin - // On the source chain, we need to verify all the transfers before has been relayed or slashed. - // So we needs to carry the the previous shash transferId to ensure that the slash is continuous. - function _slashAndRemoteRefund( - TransferParameter calldata params, - bytes32 expectedTransferId - ) internal returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_REFUND_TIMESTAMP, "slash time not expired"); - _fillTransfer(params, expectedTransferId); - - // slasher = msg.sender - slashInfos[expectedTransferId] = SlashInfo(params.provider, params.sourceToken, msg.sender); - - // Do not slash `transferId` in source chain unless `latestSlashTransferId` has been slashed - message = _encodeSlashCall( - fillTransfers[expectedTransferId], - expectedTransferId, - params.provider, - params.sourceToken, - msg.sender - ); - emit TransferFilled(expectedTransferId, msg.sender); - } - - // we use this to verify that the transfer has been slashed by user and it can resend the slash request - function _retrySlashAndRemoteRefund(bytes32 transferId) internal view returns(bytes memory message) { - bytes32 latestSlashTransferId = fillTransfers[transferId]; - // transfer must be filled - require(latestSlashTransferId != bytes32(0), "invalid transfer id"); - // transfer must be slashed - SlashInfo memory slashInfo = slashInfos[transferId]; - require(slashInfo.slasher != address(0), "slasher not exist"); - message = _encodeSlashCall( - latestSlashTransferId, - transferId, - slashInfo.provider, - slashInfo.sourceToken, - slashInfo.slasher - ); - } - - function _encodeSlashCall( - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) internal pure returns(bytes memory) { - return abi.encodeWithSelector( - ILnOppositeBridgeSource.slash.selector, - latestSlashTransferId, - transferId, - provider, - sourceToken, - slasher - ); - } - - function _requestWithdrawMargin( - bytes32 lastTransferId, - address sourceToken, - uint112 amount - ) internal view returns(bytes memory message) { - bytes32 latestSlashTransferId = fillTransfers[lastTransferId]; - require(latestSlashTransferId != bytes32(0), "invalid last transfer"); - - return abi.encodeWithSelector( - ILnOppositeBridgeSource.withdrawMargin.selector, - latestSlashTransferId, - lastTransferId, - msg.sender, - sourceToken, - amount - ); - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @arbitrum/nitro-contracts/src/bridge/IOwnable.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.4.21 <0.9.0; - -interface IOwnable { - function owner() external view returns (address); -} - -// File @arbitrum/nitro-contracts/src/bridge/IBridge.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IBridge { - event MessageDelivered( - uint256 indexed messageIndex, - bytes32 indexed beforeInboxAcc, - address inbox, - uint8 kind, - address sender, - bytes32 messageDataHash, - uint256 baseFeeL1, - uint64 timestamp - ); - - event BridgeCallTriggered( - address indexed outbox, - address indexed to, - uint256 value, - bytes data - ); - - event InboxToggle(address indexed inbox, bool enabled); - - event OutboxToggle(address indexed outbox, bool enabled); - - event SequencerInboxUpdated(address newSequencerInbox); - - function allowedDelayedInboxList(uint256) external returns (address); - - function allowedOutboxList(uint256) external returns (address); - - /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. - function delayedInboxAccs(uint256) external view returns (bytes32); - - /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. - function sequencerInboxAccs(uint256) external view returns (bytes32); - - function rollup() external view returns (IOwnable); - - function sequencerInbox() external view returns (address); - - function activeOutbox() external view returns (address); - - function allowedDelayedInboxes(address inbox) external view returns (bool); - - function allowedOutboxes(address outbox) external view returns (bool); - - function sequencerReportedSubMessageCount() external view returns (uint256); - - /** - * @dev Enqueue a message in the delayed inbox accumulator. - * These messages are later sequenced in the SequencerInbox, either - * by the sequencer as part of a normal batch, or by force inclusion. - */ - function enqueueDelayedMessage( - uint8 kind, - address sender, - bytes32 messageDataHash - ) external payable returns (uint256); - - function executeCall( - address to, - uint256 value, - bytes calldata data - ) external returns (bool success, bytes memory returnData); - - function delayedMessageCount() external view returns (uint256); - - function sequencerMessageCount() external view returns (uint256); - - // ---------- onlySequencerInbox functions ---------- - - function enqueueSequencerMessage( - bytes32 dataHash, - uint256 afterDelayedMessagesRead, - uint256 prevMessageCount, - uint256 newMessageCount - ) - external - returns ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 acc - ); - - /** - * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type - * This is done through a separate function entrypoint instead of allowing the sequencer inbox - * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either - * every delayed inbox or every sequencer inbox call. - */ - function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) - external - returns (uint256 msgNum); - - // ---------- onlyRollupOrOwner functions ---------- - - function setSequencerInbox(address _sequencerInbox) external; - - function setDelayedInbox(address inbox, bool enabled) external; - - function setOutbox(address inbox, bool enabled) external; - - // ---------- initializer ---------- - - function initialize(IOwnable rollup_) external; -} - -// File @arbitrum/nitro-contracts/src/bridge/IDelayedMessageProvider.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IDelayedMessageProvider { - /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator - event InboxMessageDelivered(uint256 indexed messageNum, bytes data); - - /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator - /// same as InboxMessageDelivered but the batch data is available in tx.input - event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); -} - -// File @arbitrum/nitro-contracts/src/libraries/IGasRefunder.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IGasRefunder { - function onGasSpent( - address payable spender, - uint256 gasUsed, - uint256 calldataSize - ) external returns (bool success); -} - -abstract contract GasRefundEnabled { - /// @dev this refunds the sender for execution costs of the tx - /// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging - /// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded - modifier refundsGas(IGasRefunder gasRefunder) { - uint256 startGasLeft = gasleft(); - _; - if (address(gasRefunder) != address(0)) { - uint256 calldataSize; - assembly { - calldataSize := calldatasize() - } - uint256 calldataWords = (calldataSize + 31) / 32; - // account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost - startGasLeft += calldataWords * 6 + (calldataWords**2) / 512; - // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call - // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input - // solhint-disable-next-line avoid-tx-origin - if (msg.sender != tx.origin) { - // We can't be sure if this calldata came from the top level tx, - // so to be safe we tell the gas refunder there was no calldata. - calldataSize = 0; - } - gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize); - } - } -} - -// File @arbitrum/nitro-contracts/src/bridge/ISequencerInbox.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; -pragma experimental ABIEncoderV2; - - - -interface ISequencerInbox is IDelayedMessageProvider { - struct MaxTimeVariation { - uint256 delayBlocks; - uint256 futureBlocks; - uint256 delaySeconds; - uint256 futureSeconds; - } - - struct TimeBounds { - uint64 minTimestamp; - uint64 maxTimestamp; - uint64 minBlockNumber; - uint64 maxBlockNumber; - } - - enum BatchDataLocation { - TxInput, - SeparateBatchEvent, - NoData - } - - event SequencerBatchDelivered( - uint256 indexed batchSequenceNumber, - bytes32 indexed beforeAcc, - bytes32 indexed afterAcc, - bytes32 delayedAcc, - uint256 afterDelayedMessagesRead, - TimeBounds timeBounds, - BatchDataLocation dataLocation - ); - - event OwnerFunctionCalled(uint256 indexed id); - - /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input - event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data); - - /// @dev a valid keyset was added - event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes); - - /// @dev a keyset was invalidated - event InvalidateKeyset(bytes32 indexed keysetHash); - - function totalDelayedMessagesRead() external view returns (uint256); - - function bridge() external view returns (IBridge); - - /// @dev The size of the batch header - // solhint-disable-next-line func-name-mixedcase - function HEADER_LENGTH() external view returns (uint256); - - /// @dev If the first batch data byte after the header has this bit set, - /// the sequencer inbox has authenticated the data. Currently not used. - // solhint-disable-next-line func-name-mixedcase - function DATA_AUTHENTICATED_FLAG() external view returns (bytes1); - - function rollup() external view returns (IOwnable); - - function isBatchPoster(address) external view returns (bool); - - struct DasKeySetInfo { - bool isValidKeyset; - uint64 creationBlock; - } - - // https://github.com/ethereum/solidity/issues/11826 - // function maxTimeVariation() external view returns (MaxTimeVariation calldata); - // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata); - - /// @notice Remove force inclusion delay after a L1 chainId fork - function removeDelayAfterFork() external; - - /// @notice Force messages from the delayed inbox to be included in the chain - /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and - /// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these - /// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages. - /// @param _totalDelayedMessagesRead The total number of messages to read up to - /// @param kind The kind of the last message to be included - /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included - /// @param baseFeeL1 The l1 gas price of the last message to be included - /// @param sender The sender of the last message to be included - /// @param messageDataHash The messageDataHash of the last message to be included - function forceInclusion( - uint256 _totalDelayedMessagesRead, - uint8 kind, - uint64[2] calldata l1BlockAndTime, - uint256 baseFeeL1, - address sender, - bytes32 messageDataHash - ) external; - - function inboxAccs(uint256 index) external view returns (bytes32); - - function batchCount() external view returns (uint256); - - function isValidKeysetHash(bytes32 ksHash) external view returns (bool); - - /// @notice the creation block is intended to still be available after a keyset is deleted - function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256); - - // ---------- BatchPoster functions ---------- - - function addSequencerL2BatchFromOrigin( - uint256 sequenceNumber, - bytes calldata data, - uint256 afterDelayedMessagesRead, - IGasRefunder gasRefunder - ) external; - - function addSequencerL2Batch( - uint256 sequenceNumber, - bytes calldata data, - uint256 afterDelayedMessagesRead, - IGasRefunder gasRefunder, - uint256 prevMessageCount, - uint256 newMessageCount - ) external; - - // ---------- onlyRollupOrOwner functions ---------- - - /** - * @notice Set max delay for sequencer inbox - * @param maxTimeVariation_ the maximum time variation parameters - */ - function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external; - - /** - * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox - * @param addr the address - * @param isBatchPoster_ if the specified address should be authorized as a batch poster - */ - function setIsBatchPoster(address addr, bool isBatchPoster_) external; - - /** - * @notice Makes Data Availability Service keyset valid - * @param keysetBytes bytes of the serialized keyset - */ - function setValidKeyset(bytes calldata keysetBytes) external; - - /** - * @notice Invalidates a Data Availability Service keyset - * @param ksHash hash of the keyset - */ - function invalidateKeysetHash(bytes32 ksHash) external; - - // ---------- initializer ---------- - - function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external; -} - -// File @arbitrum/nitro-contracts/src/bridge/IInbox.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - - - -interface IInbox is IDelayedMessageProvider { - function bridge() external view returns (IBridge); - - function sequencerInbox() external view returns (ISequencerInbox); - - /** - * @notice Send a generic L2 message to the chain - * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input - * This method will be disabled upon L1 fork to prevent replay attacks on L2 - * @param messageData Data of the message being sent - */ - function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256); - - /** - * @notice Send a generic L2 message to the chain - * @dev This method can be used to send any type of message that doesn't require L1 validation - * This method will be disabled upon L1 fork to prevent replay attacks on L2 - * @param messageData Data of the message being sent - */ - function sendL2Message(bytes calldata messageData) external returns (uint256); - - function sendL1FundedUnsignedTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - bytes calldata data - ) external payable returns (uint256); - - function sendL1FundedContractTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - address to, - bytes calldata data - ) external payable returns (uint256); - - function sendUnsignedTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - function sendContractTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - /** - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendL1FundedUnsignedTransactionToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - bytes calldata data - ) external payable returns (uint256); - - /** - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendUnsignedTransactionToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - /** - * @notice Send a message to initiate L2 withdrawal - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendWithdrawEthToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - uint256 value, - address withdrawTo - ) external returns (uint256); - - /** - * @notice Get the L1 fee for submitting a retryable - * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value - * @dev This formula may change in the future, to future proof your code query this method instead of inlining!! - * @param dataLength The length of the retryable's calldata, in bytes - * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used - */ - function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) - external - view - returns (uint256); - - /** - * @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract - * @dev This does not trigger the fallback function when receiving in the L2 side. - * Look into retryable tickets if you are interested in this functionality. - * @dev This function should not be called inside contract constructors - */ - function depositEth() external payable returns (uint256); - - /** - * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts - * @dev all msg.value will deposited to callValueRefundAddress on L2 - * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error - * @param to destination L2 contract address - * @param l2CallValue call value for retryable L2 message - * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance - * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled - * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param data ABI encoded data of L2 message - * @return unique message number of the retryable transaction - */ - function createRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); - - /** - * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts - * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds - * come from the deposit alone, rather than falling back on the user's L2 balance - * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). - * createRetryableTicket method is the recommended standard. - * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error - * @param to destination L2 contract address - * @param l2CallValue call value for retryable L2 message - * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance - * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled - * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param data ABI encoded data of L2 message - * @return unique message number of the retryable transaction - */ - function unsafeCreateRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); - - // ---------- onlyRollupOrOwner functions ---------- - - /// @notice pauses all inbox functionality - function pause() external; - - /// @notice unpauses all inbox functionality - function unpause() external; - - // ---------- initializer ---------- - - /** - * @dev function to be called one time during the inbox upgrade process - * this is used to fix the storage slots - */ - function postUpgradeInit(IBridge _bridge) external; - - function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external; -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Arb2EthTarget.sol -// License-Identifier: MIT - - - - -contract Arb2EthTarget is Initializable, LnAccessController, LnOppositeBridgeTarget { - IInbox public inbox; - address public remoteBridge; - - event WithdrawMargin(bytes32 lastTransferId, uint112 amount); - - receive() external payable {} - - function initialize(address _dao, address _inbox) public initializer { - inbox = IInbox(_inbox); - _initialize(_dao); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function submissionRefundFee( - uint256 baseFee, - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher, - uint256 percentIncrease - ) external view returns(uint256) { - bytes memory slashCall = _encodeSlashCall( - latestSlashTransferId, - transferId, - provider, - sourceToken, - slasher - ); - uint256 fee = inbox.calculateRetryableSubmissionFee(slashCall.length, baseFee); - return fee + fee * percentIncrease / 100; - } - - function submissionWithdrawFee( - uint256 baseFee, - bytes32 lastTransferId, - address sourceToken, - uint112 amount, - uint256 percentIncrease - ) external view returns(uint256) { - bytes memory withdrawCall = _requestWithdrawMargin( - lastTransferId, - sourceToken, - amount - ); - uint256 fee = inbox.calculateRetryableSubmissionFee(withdrawCall.length, baseFee); - return fee + fee * percentIncrease / 100; - } - - function _sendMessage( - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid, - bytes memory message, - uint256 prepaid - ) internal returns(uint256) { - return inbox.createRetryableTicket{ value: prepaid }( - remoteBridge, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - message - ); - } - - function slashAndRemoteRefund( - TransferParameter calldata params, - bytes32 expectedTransferId, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) payable external whenNotPaused { - bytes memory refundCallMessage = _slashAndRemoteRefund( - params, - expectedTransferId - ); - uint256 valueUsed = address(0) == params.targetToken ? params.amount : 0; - _sendMessage(maxSubmissionCost, maxGas, gasPriceBid, refundCallMessage, msg.value - valueUsed); - } - - function retryRemoteRefund( - bytes32 transferId, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) payable external whenNotPaused { - bytes memory refundCallMessage = _retrySlashAndRemoteRefund(transferId); - _sendMessage(maxSubmissionCost, maxGas, gasPriceBid, refundCallMessage, msg.value); - } - - function requestWithdrawMargin( - bytes32 lastTransferId, - address sourceToken, - uint112 amount, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) payable external whenNotPaused { - bytes memory cancelWithdrawMarginCall = _requestWithdrawMargin( - lastTransferId, - sourceToken, - amount - ); - _sendMessage(maxSubmissionCost, maxGas, gasPriceBid, cancelWithdrawMarginCall, msg.value); - emit WithdrawMargin(lastTransferId, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ArbReceiveService.sol b/helix-contract/flatten/lnv2/Eth2ArbReceiveService.sol new file mode 100644 index 00000000..28c7c395 --- /dev/null +++ b/helix-contract/flatten/lnv2/Eth2ArbReceiveService.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: MIT + +/** + * .----------------. .----------------. .----------------. .----------------. .----------------. + * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | + * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | + * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | + * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | + * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | + * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | + * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | + * | | | || | | || | | || | | || | | | + * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | + * '----------------' '----------------' '----------------' '----------------' '----------------' ' + * + * + * 10/17/2023 + **/ + +pragma solidity ^0.8.17; + +// File contracts/ln/base/LnAccessController.sol +// License-Identifier: MIT + +/// @title LnAccessController +/// @notice LnAccessController is a contract to control the access permission +/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract +contract LnAccessController { + address public dao; + address public operator; + + mapping(address=>bool) public callerWhiteList; + + modifier onlyDao() { + require(msg.sender == dao, "!dao"); + _; + } + + modifier onlyOperator() { + require(msg.sender == operator, "!operator"); + _; + } + + modifier onlyWhiteListCaller() { + require(callerWhiteList[msg.sender], "caller not in white list"); + _; + } + + function _initialize(address _dao) internal { + dao = _dao; + operator = _dao; + } + + function setOperator(address _operator) onlyDao external { + operator = _operator; + } + + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { + callerWhiteList[appAddress] = enable; + } + + function transferOwnership(address _dao) onlyDao external { + dao = _dao; + } +} + +// File contracts/ln/interface/ILowLevelMessager.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 @arbitrum/nitro-contracts/src/libraries/AddressAliasHelper.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + + +library AddressAliasHelper { + uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); + + /// @notice Utility function that converts the address in the L1 that submitted a tx to + /// the inbox to the msg.sender viewed in the L2 + /// @param l1Address the address in the L1 that triggered the tx to L2 + /// @return l2Address L2 address as viewed in msg.sender + function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { + unchecked { + l2Address = address(uint160(l1Address) + OFFSET); + } + } + + /// @notice Utility function that converts the msg.sender viewed in the L2 to the + /// address in the L1 that submitted a tx to the inbox + /// @param l2Address L2 address as viewed in msg.sender + /// @return l1Address the address in the L1 that triggered the tx to L2 + function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { + unchecked { + l1Address = address(uint160(l2Address) - OFFSET); + } + } +} + +// File contracts/ln/messager/Eth2ArbReceiveService.sol +// License-Identifier: MIT + + + +// from ethereum to arbitrum messager +contract Eth2ArbReceiveService is ILowLevelMessageReceiver, LnAccessController { + uint256 immutable public REMOTE_CHAINID; + address public remoteMessagerAlias; + + mapping(address=>address) public appPairs; + + modifier onlyRemoteBridge() { + require(msg.sender == remoteMessagerAlias, "invalid remote caller"); + _; + } + + constructor(address _dao, uint256 _remoteChainId) { + _initialize(_dao); + REMOTE_CHAINID = _remoteChainId; + } + + function setRemoteMessager(address _remoteMessager) onlyDao external { + remoteMessagerAlias = AddressAliasHelper.applyL1ToL2Alias(_remoteMessager); + } + + function registerRemoteSender(uint256 _remoteChainId, address _remoteBridge) onlyWhiteListCaller external { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + appPairs[msg.sender] = _remoteBridge; + } + + function recvMessage(address _remoteApp, address _localApp, bytes memory _message) onlyRemoteBridge external { + address remoteAppAddress = appPairs[_localApp]; + require(remoteAppAddress == _remoteApp, "invalid remote app"); + (bool result,) = _localApp.call(_message); + require(result == true, "local call failed"); + } +} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ArbSendService.sol b/helix-contract/flatten/lnv2/Eth2ArbSendService.sol new file mode 100644 index 00000000..ec6ed992 --- /dev/null +++ b/helix-contract/flatten/lnv2/Eth2ArbSendService.sol @@ -0,0 +1,693 @@ +// SPDX-License-Identifier: MIT + +/** + * .----------------. .----------------. .----------------. .----------------. .----------------. + * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | + * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | + * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | + * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | + * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | + * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | + * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | + * | | | || | | || | | || | | || | | | + * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | + * '----------------' '----------------' '----------------' '----------------' '----------------' ' + * + * + * 10/17/2023 + **/ + +pragma solidity ^0.8.17; + +// File contracts/ln/base/LnAccessController.sol +// License-Identifier: MIT + +/// @title LnAccessController +/// @notice LnAccessController is a contract to control the access permission +/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract +contract LnAccessController { + address public dao; + address public operator; + + mapping(address=>bool) public callerWhiteList; + + modifier onlyDao() { + require(msg.sender == dao, "!dao"); + _; + } + + modifier onlyOperator() { + require(msg.sender == operator, "!operator"); + _; + } + + modifier onlyWhiteListCaller() { + require(callerWhiteList[msg.sender], "caller not in white list"); + _; + } + + function _initialize(address _dao) internal { + dao = _dao; + operator = _dao; + } + + function setOperator(address _operator) onlyDao external { + operator = _operator; + } + + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { + callerWhiteList[appAddress] = enable; + } + + function transferOwnership(address _dao) onlyDao external { + dao = _dao; + } +} + +// File contracts/ln/interface/ILowLevelMessager.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 @arbitrum/nitro-contracts/src/bridge/IOwnable.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.4.21 <0.9.0; + +interface IOwnable { + function owner() external view returns (address); +} + +// File @arbitrum/nitro-contracts/src/bridge/IBridge.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +interface IBridge { + event MessageDelivered( + uint256 indexed messageIndex, + bytes32 indexed beforeInboxAcc, + address inbox, + uint8 kind, + address sender, + bytes32 messageDataHash, + uint256 baseFeeL1, + uint64 timestamp + ); + + event BridgeCallTriggered( + address indexed outbox, + address indexed to, + uint256 value, + bytes data + ); + + event InboxToggle(address indexed inbox, bool enabled); + + event OutboxToggle(address indexed outbox, bool enabled); + + event SequencerInboxUpdated(address newSequencerInbox); + + function allowedDelayedInboxList(uint256) external returns (address); + + function allowedOutboxList(uint256) external returns (address); + + /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. + function delayedInboxAccs(uint256) external view returns (bytes32); + + /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. + function sequencerInboxAccs(uint256) external view returns (bytes32); + + function rollup() external view returns (IOwnable); + + function sequencerInbox() external view returns (address); + + function activeOutbox() external view returns (address); + + function allowedDelayedInboxes(address inbox) external view returns (bool); + + function allowedOutboxes(address outbox) external view returns (bool); + + function sequencerReportedSubMessageCount() external view returns (uint256); + + /** + * @dev Enqueue a message in the delayed inbox accumulator. + * These messages are later sequenced in the SequencerInbox, either + * by the sequencer as part of a normal batch, or by force inclusion. + */ + function enqueueDelayedMessage( + uint8 kind, + address sender, + bytes32 messageDataHash + ) external payable returns (uint256); + + function executeCall( + address to, + uint256 value, + bytes calldata data + ) external returns (bool success, bytes memory returnData); + + function delayedMessageCount() external view returns (uint256); + + function sequencerMessageCount() external view returns (uint256); + + // ---------- onlySequencerInbox functions ---------- + + function enqueueSequencerMessage( + bytes32 dataHash, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount + ) + external + returns ( + uint256 seqMessageIndex, + bytes32 beforeAcc, + bytes32 delayedAcc, + bytes32 acc + ); + + /** + * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type + * This is done through a separate function entrypoint instead of allowing the sequencer inbox + * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either + * every delayed inbox or every sequencer inbox call. + */ + function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) + external + returns (uint256 msgNum); + + // ---------- onlyRollupOrOwner functions ---------- + + function setSequencerInbox(address _sequencerInbox) external; + + function setDelayedInbox(address inbox, bool enabled) external; + + function setOutbox(address inbox, bool enabled) external; + + // ---------- initializer ---------- + + function initialize(IOwnable rollup_) external; +} + +// File @arbitrum/nitro-contracts/src/bridge/IDelayedMessageProvider.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +interface IDelayedMessageProvider { + /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator + event InboxMessageDelivered(uint256 indexed messageNum, bytes data); + + /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator + /// same as InboxMessageDelivered but the batch data is available in tx.input + event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); +} + +// File @arbitrum/nitro-contracts/src/libraries/IGasRefunder.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +interface IGasRefunder { + function onGasSpent( + address payable spender, + uint256 gasUsed, + uint256 calldataSize + ) external returns (bool success); +} + +abstract contract GasRefundEnabled { + /// @dev this refunds the sender for execution costs of the tx + /// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging + /// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded + modifier refundsGas(IGasRefunder gasRefunder) { + uint256 startGasLeft = gasleft(); + _; + if (address(gasRefunder) != address(0)) { + uint256 calldataSize; + assembly { + calldataSize := calldatasize() + } + uint256 calldataWords = (calldataSize + 31) / 32; + // account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost + startGasLeft += calldataWords * 6 + (calldataWords**2) / 512; + // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call + // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input + // solhint-disable-next-line avoid-tx-origin + if (msg.sender != tx.origin) { + // We can't be sure if this calldata came from the top level tx, + // so to be safe we tell the gas refunder there was no calldata. + calldataSize = 0; + } + gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize); + } + } +} + +// File @arbitrum/nitro-contracts/src/bridge/ISequencerInbox.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; +pragma experimental ABIEncoderV2; + + + +interface ISequencerInbox is IDelayedMessageProvider { + struct MaxTimeVariation { + uint256 delayBlocks; + uint256 futureBlocks; + uint256 delaySeconds; + uint256 futureSeconds; + } + + struct TimeBounds { + uint64 minTimestamp; + uint64 maxTimestamp; + uint64 minBlockNumber; + uint64 maxBlockNumber; + } + + enum BatchDataLocation { + TxInput, + SeparateBatchEvent, + NoData + } + + event SequencerBatchDelivered( + uint256 indexed batchSequenceNumber, + bytes32 indexed beforeAcc, + bytes32 indexed afterAcc, + bytes32 delayedAcc, + uint256 afterDelayedMessagesRead, + TimeBounds timeBounds, + BatchDataLocation dataLocation + ); + + event OwnerFunctionCalled(uint256 indexed id); + + /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input + event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data); + + /// @dev a valid keyset was added + event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes); + + /// @dev a keyset was invalidated + event InvalidateKeyset(bytes32 indexed keysetHash); + + function totalDelayedMessagesRead() external view returns (uint256); + + function bridge() external view returns (IBridge); + + /// @dev The size of the batch header + // solhint-disable-next-line func-name-mixedcase + function HEADER_LENGTH() external view returns (uint256); + + /// @dev If the first batch data byte after the header has this bit set, + /// the sequencer inbox has authenticated the data. Currently not used. + // solhint-disable-next-line func-name-mixedcase + function DATA_AUTHENTICATED_FLAG() external view returns (bytes1); + + function rollup() external view returns (IOwnable); + + function isBatchPoster(address) external view returns (bool); + + struct DasKeySetInfo { + bool isValidKeyset; + uint64 creationBlock; + } + + // https://github.com/ethereum/solidity/issues/11826 + // function maxTimeVariation() external view returns (MaxTimeVariation calldata); + // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata); + + /// @notice Remove force inclusion delay after a L1 chainId fork + function removeDelayAfterFork() external; + + /// @notice Force messages from the delayed inbox to be included in the chain + /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and + /// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these + /// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages. + /// @param _totalDelayedMessagesRead The total number of messages to read up to + /// @param kind The kind of the last message to be included + /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included + /// @param baseFeeL1 The l1 gas price of the last message to be included + /// @param sender The sender of the last message to be included + /// @param messageDataHash The messageDataHash of the last message to be included + function forceInclusion( + uint256 _totalDelayedMessagesRead, + uint8 kind, + uint64[2] calldata l1BlockAndTime, + uint256 baseFeeL1, + address sender, + bytes32 messageDataHash + ) external; + + function inboxAccs(uint256 index) external view returns (bytes32); + + function batchCount() external view returns (uint256); + + function isValidKeysetHash(bytes32 ksHash) external view returns (bool); + + /// @notice the creation block is intended to still be available after a keyset is deleted + function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256); + + // ---------- BatchPoster functions ---------- + + function addSequencerL2BatchFromOrigin( + uint256 sequenceNumber, + bytes calldata data, + uint256 afterDelayedMessagesRead, + IGasRefunder gasRefunder + ) external; + + function addSequencerL2Batch( + uint256 sequenceNumber, + bytes calldata data, + uint256 afterDelayedMessagesRead, + IGasRefunder gasRefunder, + uint256 prevMessageCount, + uint256 newMessageCount + ) external; + + // ---------- onlyRollupOrOwner functions ---------- + + /** + * @notice Set max delay for sequencer inbox + * @param maxTimeVariation_ the maximum time variation parameters + */ + function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external; + + /** + * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox + * @param addr the address + * @param isBatchPoster_ if the specified address should be authorized as a batch poster + */ + function setIsBatchPoster(address addr, bool isBatchPoster_) external; + + /** + * @notice Makes Data Availability Service keyset valid + * @param keysetBytes bytes of the serialized keyset + */ + function setValidKeyset(bytes calldata keysetBytes) external; + + /** + * @notice Invalidates a Data Availability Service keyset + * @param ksHash hash of the keyset + */ + function invalidateKeysetHash(bytes32 ksHash) external; + + // ---------- initializer ---------- + + function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external; +} + +// File @arbitrum/nitro-contracts/src/bridge/IInbox.sol@v1.0.1 +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + + + +interface IInbox is IDelayedMessageProvider { + function bridge() external view returns (IBridge); + + function sequencerInbox() external view returns (ISequencerInbox); + + /** + * @notice Send a generic L2 message to the chain + * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input + * This method will be disabled upon L1 fork to prevent replay attacks on L2 + * @param messageData Data of the message being sent + */ + function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256); + + /** + * @notice Send a generic L2 message to the chain + * @dev This method can be used to send any type of message that doesn't require L1 validation + * This method will be disabled upon L1 fork to prevent replay attacks on L2 + * @param messageData Data of the message being sent + */ + function sendL2Message(bytes calldata messageData) external returns (uint256); + + function sendL1FundedUnsignedTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 nonce, + address to, + bytes calldata data + ) external payable returns (uint256); + + function sendL1FundedContractTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, + address to, + bytes calldata data + ) external payable returns (uint256); + + function sendUnsignedTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 nonce, + address to, + uint256 value, + bytes calldata data + ) external returns (uint256); + + function sendContractTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, + address to, + uint256 value, + bytes calldata data + ) external returns (uint256); + + /** + * @dev This method can only be called upon L1 fork and will not alias the caller + * This method will revert if not called from origin + */ + function sendL1FundedUnsignedTransactionToFork( + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 nonce, + address to, + bytes calldata data + ) external payable returns (uint256); + + /** + * @dev This method can only be called upon L1 fork and will not alias the caller + * This method will revert if not called from origin + */ + function sendUnsignedTransactionToFork( + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 nonce, + address to, + uint256 value, + bytes calldata data + ) external returns (uint256); + + /** + * @notice Send a message to initiate L2 withdrawal + * @dev This method can only be called upon L1 fork and will not alias the caller + * This method will revert if not called from origin + */ + function sendWithdrawEthToFork( + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 nonce, + uint256 value, + address withdrawTo + ) external returns (uint256); + + /** + * @notice Get the L1 fee for submitting a retryable + * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value + * @dev This formula may change in the future, to future proof your code query this method instead of inlining!! + * @param dataLength The length of the retryable's calldata, in bytes + * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used + */ + function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) + external + view + returns (uint256); + + /** + * @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract + * @dev This does not trigger the fallback function when receiving in the L2 side. + * Look into retryable tickets if you are interested in this functionality. + * @dev This function should not be called inside contract constructors + */ + function depositEth() external payable returns (uint256); + + /** + * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts + * @dev all msg.value will deposited to callValueRefundAddress on L2 + * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error + * @param to destination L2 contract address + * @param l2CallValue call value for retryable L2 message + * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance + * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled + * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ + function createRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + bytes calldata data + ) external payable returns (uint256); + + /** + * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts + * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds + * come from the deposit alone, rather than falling back on the user's L2 balance + * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). + * createRetryableTicket method is the recommended standard. + * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error + * @param to destination L2 contract address + * @param l2CallValue call value for retryable L2 message + * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance + * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled + * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ + function unsafeCreateRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + bytes calldata data + ) external payable returns (uint256); + + // ---------- onlyRollupOrOwner functions ---------- + + /// @notice pauses all inbox functionality + function pause() external; + + /// @notice unpauses all inbox functionality + function unpause() external; + + // ---------- initializer ---------- + + /** + * @dev function to be called one time during the inbox upgrade process + * this is used to fix the storage slots + */ + function postUpgradeInit(IBridge _bridge) external; + + function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external; +} + +// File contracts/ln/messager/Eth2ArbSendService.sol +// License-Identifier: MIT + + + +// from ethereum to arbitrum messager +contract Eth2ArbSendService is ILowLevelMessageSender, LnAccessController { + uint256 immutable public REMOTE_CHAINID; + IInbox public inbox; + address public remoteMessager; + mapping(address=>address) public appPairs; + + constructor(address _dao, address _inbox, uint256 _remoteChainId) { + _initialize(_dao); + inbox = IInbox(_inbox); + REMOTE_CHAINID = _remoteChainId; + } + + function setRemoteMessager(address _remoteMessager) onlyDao external { + remoteMessager = _remoteMessager; + } + + function registerRemoteReceiver(uint256 _remoteChainId, address _remoteBridge) onlyWhiteListCaller external { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + appPairs[msg.sender] = _remoteBridge; + } + + function sendMessage(uint256 _remoteChainId, bytes memory _message, bytes memory _params) onlyWhiteListCaller external payable { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + address remoteAppAddress = appPairs[msg.sender]; + require(remoteAppAddress != address(0), "app not registered"); + + (uint256 maxSubmissionCost, uint256 l2GasPrice, uint256 l2GasLimit, address refunder) = abi.decode(_params, (uint256, uint256, uint256, address)); + + bytes memory remoteReceiveCall = abi.encodeWithSelector( + ILowLevelMessageReceiver.recvMessage.selector, + msg.sender, + remoteAppAddress, + _message + ); + inbox.createRetryableTicket{value: msg.value}( + remoteMessager, + 0, + maxSubmissionCost, + refunder, + refunder, + l2GasLimit, + l2GasPrice, + remoteReceiveCall + ); + } + + function fee( + uint256 _callSize, + uint256 _l1GasPrice, + uint256 _l2GasPrice, + uint256 _l2GasLimit, + uint256 _percentIncrease + ) external view returns(uint256, uint256) { + uint256 submissionFee = inbox.calculateRetryableSubmissionFee(_callSize, _l1GasPrice); + uint256 scaleSubmissionFee = submissionFee + submissionFee * _percentIncrease / 100; + return (scaleSubmissionFee, scaleSubmissionFee + _l2GasPrice * _l2GasLimit); + } + + function encodeParams( + uint256 _maxSubmissionCost, + uint256 _l2GasPrice, + uint256 _l2GasLimit, + address _refunder + ) external pure returns(bytes memory) { + return abi.encode(_maxSubmissionCost, _l2GasPrice, _l2GasLimit, _refunder); + } +} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ArbSource.sol b/helix-contract/flatten/lnv2/Eth2ArbSource.sol deleted file mode 100644 index 037e7d4d..00000000 --- a/helix-contract/flatten/lnv2/Eth2ArbSource.sol +++ /dev/null @@ -1,2646 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/11/2023 - **/ - -pragma solidity ^0.8.10; - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/interface/ILnDefaultBridgeTarget.sol -// License-Identifier: MIT - - -interface ILnDefaultBridgeTarget { - function slash( - LnBridgeHelper.TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external; - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external; -} - -// File contracts/ln/base/LnDefaultBridgeSource.sol -// License-Identifier: MIT - - - -/// @title LnPositiveBridgeSource -/// @notice LnPositiveBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can send a slash request message to target chain, then force transfer from lnProvider's margin to the user. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnDefaultBridgeSource is LnBridgeHelper { - // the time(seconds) for liquidity provider to delivery message - // if timeout, slasher can work. - uint256 constant public MIN_SLASH_TIMESTAMP = 30 * 60; - // liquidity fee base rate - // liquidityFee = liquidityFeeRate / LIQUIDITY_FEE_RATE_BASE * sendAmount - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - // max transfer amount one time - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - - // provider fee is paid to liquidity node's account - // the fee is charged by the same token that user transfered - // providerFee = baseFee + liquidityFeeRate/LIQUIDITY_FEE_RATE_BASE * sendAmount - struct LnProviderFee { - uint112 baseFee; - uint8 liquidityFeeRate; - } - - struct LnProviderInfo { - LnProviderFee fee; - // we use this nonce to generate the unique withdraw id - uint64 withdrawNonce; - bytes32 lastTransferId; - } - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId or withdrawNonce updated, revert - // 2. if totalFee increase, revert - // 3. if totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 totalFee; - uint64 withdrawNonce; - } - - // lock info - // the fee and penalty is the state of the transfer confirmed - struct LockInfo { - uint112 fee; - uint112 penalty; - bool isLocked; - } - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // providerKey => provider info - mapping(bytes32=>LnProviderInfo) public lnProviders; - // transferId => lock info - mapping(bytes32=>LockInfo) public lockInfos; - - address public protocolFeeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LnProviderUpdated(address provider, address sourceToken, uint112 baseFee, uint8 liquidityfeeRate); - - // protocolFeeReceiver is the protocol fee reciever, we don't use the contract itself as the receiver - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - protocolFeeReceiver = _feeReceiver; - } - - // register or update token info, it can be only called by contract owner - // source token can only map a unique target token on target chain - function _setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) internal { - tokenInfos[_sourceToken] = TokenInfo( - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals, - true - ); - } - - // lnProvider register - // 1. set fee on source chain - // 2. deposit margin on target chain - function setProviderFee( - address sourceToken, - uint112 baseFee, - uint8 liquidityFeeRate - ) external { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderFee memory providerFee = LnProviderFee(baseFee, liquidityFeeRate); - - // we only update the field fee of the provider info - // if the provider has not been registered, then this line will register, otherwise update fee - lnProviders[providerKey].fee = providerFee; - - emit LnProviderUpdated(msg.sender, sourceToken, baseFee, liquidityFeeRate); - } - - function calculateProviderFee(LnProviderFee memory fee, uint112 amount) internal pure returns(uint256) { - return uint256(fee.baseFee) + uint256(fee.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - return providerFee + tokenInfo.protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, withdrawNonce) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(snapshot.provider, snapshot.sourceToken, tokenInfo.targetToken); - - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired:transfer"); - require(snapshot.withdrawNonce == providerInfo.withdrawNonce, "snapshot expired:withdraw"); - require(snapshot.totalFee >= providerFee + tokenInfo.protocolFee && providerFee > 0, "fee is invalid"); - - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(amount)); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - targetAmount - )); - require(!lockInfos[transferId].isLocked, "transferId exist"); - // if the transfer refund, then the fee and penalty should be given to slasher, but the protocol fee is ignored - // and we use the penalty value configure at the moment transfer confirmed - lockInfos[transferId] = LockInfo(snapshot.totalFee, tokenInfo.penaltyLnCollateral, true); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(protocolFeeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - protocolFeeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - targetAmount, - uint112(providerFee), - timestamp, - receiver); - } - - function _sourceAmountToTargetAmount( - TokenInfo memory tokenInfo, - uint256 amount - ) internal pure returns(uint112) { - uint256 targetAmount = amount * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - return uint112(targetAmount); - } - - function _slashAndRemoteRelease( - TransferParameter memory params, - bytes32 expectedTransferId - ) internal view returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "invalid timestamp"); - TokenInfo memory tokenInfo = tokenInfos[params.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(params.amount)); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - targetAmount - )); - require(expectedTransferId == transferId, "expected transfer id not match"); - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.isLocked, "lock info not match"); - uint112 targetFee = _sourceAmountToTargetAmount(tokenInfo, lockInfo.fee); - uint112 targetPenalty = _sourceAmountToTargetAmount(tokenInfo, lockInfo.penalty); - - message = _encodeSlashCall( - params, - msg.sender, - targetFee, - targetPenalty - ); - } - - function _withdrawMargin( - address sourceToken, - uint112 amount - ) internal returns(bytes memory message) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - lnProviders[providerKey].withdrawNonce = providerInfo.withdrawNonce + 1; - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, amount); - message = _encodeWithdrawCall( - providerInfo.lastTransferId, - providerInfo.withdrawNonce + 1, - msg.sender, - sourceToken, - tokenInfo.targetToken, - targetAmount - ); - } - - function _encodeSlashCall( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.slash.selector, - params, - slasher, - fee, - penalty - ); - } - - function _encodeWithdrawCall( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.withdraw.selector, - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @arbitrum/nitro-contracts/src/bridge/IOwnable.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.4.21 <0.9.0; - -interface IOwnable { - function owner() external view returns (address); -} - -// File @arbitrum/nitro-contracts/src/bridge/IBridge.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IBridge { - event MessageDelivered( - uint256 indexed messageIndex, - bytes32 indexed beforeInboxAcc, - address inbox, - uint8 kind, - address sender, - bytes32 messageDataHash, - uint256 baseFeeL1, - uint64 timestamp - ); - - event BridgeCallTriggered( - address indexed outbox, - address indexed to, - uint256 value, - bytes data - ); - - event InboxToggle(address indexed inbox, bool enabled); - - event OutboxToggle(address indexed outbox, bool enabled); - - event SequencerInboxUpdated(address newSequencerInbox); - - function allowedDelayedInboxList(uint256) external returns (address); - - function allowedOutboxList(uint256) external returns (address); - - /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. - function delayedInboxAccs(uint256) external view returns (bytes32); - - /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. - function sequencerInboxAccs(uint256) external view returns (bytes32); - - function rollup() external view returns (IOwnable); - - function sequencerInbox() external view returns (address); - - function activeOutbox() external view returns (address); - - function allowedDelayedInboxes(address inbox) external view returns (bool); - - function allowedOutboxes(address outbox) external view returns (bool); - - function sequencerReportedSubMessageCount() external view returns (uint256); - - /** - * @dev Enqueue a message in the delayed inbox accumulator. - * These messages are later sequenced in the SequencerInbox, either - * by the sequencer as part of a normal batch, or by force inclusion. - */ - function enqueueDelayedMessage( - uint8 kind, - address sender, - bytes32 messageDataHash - ) external payable returns (uint256); - - function executeCall( - address to, - uint256 value, - bytes calldata data - ) external returns (bool success, bytes memory returnData); - - function delayedMessageCount() external view returns (uint256); - - function sequencerMessageCount() external view returns (uint256); - - // ---------- onlySequencerInbox functions ---------- - - function enqueueSequencerMessage( - bytes32 dataHash, - uint256 afterDelayedMessagesRead, - uint256 prevMessageCount, - uint256 newMessageCount - ) - external - returns ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 acc - ); - - /** - * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type - * This is done through a separate function entrypoint instead of allowing the sequencer inbox - * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either - * every delayed inbox or every sequencer inbox call. - */ - function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) - external - returns (uint256 msgNum); - - // ---------- onlyRollupOrOwner functions ---------- - - function setSequencerInbox(address _sequencerInbox) external; - - function setDelayedInbox(address inbox, bool enabled) external; - - function setOutbox(address inbox, bool enabled) external; - - // ---------- initializer ---------- - - function initialize(IOwnable rollup_) external; -} - -// File @arbitrum/nitro-contracts/src/bridge/IDelayedMessageProvider.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IDelayedMessageProvider { - /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator - event InboxMessageDelivered(uint256 indexed messageNum, bytes data); - - /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator - /// same as InboxMessageDelivered but the batch data is available in tx.input - event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); -} - -// File @arbitrum/nitro-contracts/src/libraries/IGasRefunder.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - -interface IGasRefunder { - function onGasSpent( - address payable spender, - uint256 gasUsed, - uint256 calldataSize - ) external returns (bool success); -} - -abstract contract GasRefundEnabled { - /// @dev this refunds the sender for execution costs of the tx - /// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging - /// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded - modifier refundsGas(IGasRefunder gasRefunder) { - uint256 startGasLeft = gasleft(); - _; - if (address(gasRefunder) != address(0)) { - uint256 calldataSize; - assembly { - calldataSize := calldatasize() - } - uint256 calldataWords = (calldataSize + 31) / 32; - // account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost - startGasLeft += calldataWords * 6 + (calldataWords**2) / 512; - // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call - // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input - // solhint-disable-next-line avoid-tx-origin - if (msg.sender != tx.origin) { - // We can't be sure if this calldata came from the top level tx, - // so to be safe we tell the gas refunder there was no calldata. - calldataSize = 0; - } - gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize); - } - } -} - -// File @arbitrum/nitro-contracts/src/bridge/ISequencerInbox.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; -pragma experimental ABIEncoderV2; - - - -interface ISequencerInbox is IDelayedMessageProvider { - struct MaxTimeVariation { - uint256 delayBlocks; - uint256 futureBlocks; - uint256 delaySeconds; - uint256 futureSeconds; - } - - struct TimeBounds { - uint64 minTimestamp; - uint64 maxTimestamp; - uint64 minBlockNumber; - uint64 maxBlockNumber; - } - - enum BatchDataLocation { - TxInput, - SeparateBatchEvent, - NoData - } - - event SequencerBatchDelivered( - uint256 indexed batchSequenceNumber, - bytes32 indexed beforeAcc, - bytes32 indexed afterAcc, - bytes32 delayedAcc, - uint256 afterDelayedMessagesRead, - TimeBounds timeBounds, - BatchDataLocation dataLocation - ); - - event OwnerFunctionCalled(uint256 indexed id); - - /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input - event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data); - - /// @dev a valid keyset was added - event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes); - - /// @dev a keyset was invalidated - event InvalidateKeyset(bytes32 indexed keysetHash); - - function totalDelayedMessagesRead() external view returns (uint256); - - function bridge() external view returns (IBridge); - - /// @dev The size of the batch header - // solhint-disable-next-line func-name-mixedcase - function HEADER_LENGTH() external view returns (uint256); - - /// @dev If the first batch data byte after the header has this bit set, - /// the sequencer inbox has authenticated the data. Currently not used. - // solhint-disable-next-line func-name-mixedcase - function DATA_AUTHENTICATED_FLAG() external view returns (bytes1); - - function rollup() external view returns (IOwnable); - - function isBatchPoster(address) external view returns (bool); - - struct DasKeySetInfo { - bool isValidKeyset; - uint64 creationBlock; - } - - // https://github.com/ethereum/solidity/issues/11826 - // function maxTimeVariation() external view returns (MaxTimeVariation calldata); - // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata); - - /// @notice Remove force inclusion delay after a L1 chainId fork - function removeDelayAfterFork() external; - - /// @notice Force messages from the delayed inbox to be included in the chain - /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and - /// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these - /// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages. - /// @param _totalDelayedMessagesRead The total number of messages to read up to - /// @param kind The kind of the last message to be included - /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included - /// @param baseFeeL1 The l1 gas price of the last message to be included - /// @param sender The sender of the last message to be included - /// @param messageDataHash The messageDataHash of the last message to be included - function forceInclusion( - uint256 _totalDelayedMessagesRead, - uint8 kind, - uint64[2] calldata l1BlockAndTime, - uint256 baseFeeL1, - address sender, - bytes32 messageDataHash - ) external; - - function inboxAccs(uint256 index) external view returns (bytes32); - - function batchCount() external view returns (uint256); - - function isValidKeysetHash(bytes32 ksHash) external view returns (bool); - - /// @notice the creation block is intended to still be available after a keyset is deleted - function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256); - - // ---------- BatchPoster functions ---------- - - function addSequencerL2BatchFromOrigin( - uint256 sequenceNumber, - bytes calldata data, - uint256 afterDelayedMessagesRead, - IGasRefunder gasRefunder - ) external; - - function addSequencerL2Batch( - uint256 sequenceNumber, - bytes calldata data, - uint256 afterDelayedMessagesRead, - IGasRefunder gasRefunder, - uint256 prevMessageCount, - uint256 newMessageCount - ) external; - - // ---------- onlyRollupOrOwner functions ---------- - - /** - * @notice Set max delay for sequencer inbox - * @param maxTimeVariation_ the maximum time variation parameters - */ - function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external; - - /** - * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox - * @param addr the address - * @param isBatchPoster_ if the specified address should be authorized as a batch poster - */ - function setIsBatchPoster(address addr, bool isBatchPoster_) external; - - /** - * @notice Makes Data Availability Service keyset valid - * @param keysetBytes bytes of the serialized keyset - */ - function setValidKeyset(bytes calldata keysetBytes) external; - - /** - * @notice Invalidates a Data Availability Service keyset - * @param ksHash hash of the keyset - */ - function invalidateKeysetHash(bytes32 ksHash) external; - - // ---------- initializer ---------- - - function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external; -} - -// File @arbitrum/nitro-contracts/src/bridge/IInbox.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - -// solhint-disable-next-line compiler-version -pragma solidity >=0.6.9 <0.9.0; - - - -interface IInbox is IDelayedMessageProvider { - function bridge() external view returns (IBridge); - - function sequencerInbox() external view returns (ISequencerInbox); - - /** - * @notice Send a generic L2 message to the chain - * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input - * This method will be disabled upon L1 fork to prevent replay attacks on L2 - * @param messageData Data of the message being sent - */ - function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256); - - /** - * @notice Send a generic L2 message to the chain - * @dev This method can be used to send any type of message that doesn't require L1 validation - * This method will be disabled upon L1 fork to prevent replay attacks on L2 - * @param messageData Data of the message being sent - */ - function sendL2Message(bytes calldata messageData) external returns (uint256); - - function sendL1FundedUnsignedTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - bytes calldata data - ) external payable returns (uint256); - - function sendL1FundedContractTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - address to, - bytes calldata data - ) external payable returns (uint256); - - function sendUnsignedTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - function sendContractTransaction( - uint256 gasLimit, - uint256 maxFeePerGas, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - /** - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendL1FundedUnsignedTransactionToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - bytes calldata data - ) external payable returns (uint256); - - /** - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendUnsignedTransactionToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - address to, - uint256 value, - bytes calldata data - ) external returns (uint256); - - /** - * @notice Send a message to initiate L2 withdrawal - * @dev This method can only be called upon L1 fork and will not alias the caller - * This method will revert if not called from origin - */ - function sendWithdrawEthToFork( - uint256 gasLimit, - uint256 maxFeePerGas, - uint256 nonce, - uint256 value, - address withdrawTo - ) external returns (uint256); - - /** - * @notice Get the L1 fee for submitting a retryable - * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value - * @dev This formula may change in the future, to future proof your code query this method instead of inlining!! - * @param dataLength The length of the retryable's calldata, in bytes - * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used - */ - function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) - external - view - returns (uint256); - - /** - * @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract - * @dev This does not trigger the fallback function when receiving in the L2 side. - * Look into retryable tickets if you are interested in this functionality. - * @dev This function should not be called inside contract constructors - */ - function depositEth() external payable returns (uint256); - - /** - * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts - * @dev all msg.value will deposited to callValueRefundAddress on L2 - * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error - * @param to destination L2 contract address - * @param l2CallValue call value for retryable L2 message - * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance - * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled - * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param data ABI encoded data of L2 message - * @return unique message number of the retryable transaction - */ - function createRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); - - /** - * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts - * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds - * come from the deposit alone, rather than falling back on the user's L2 balance - * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). - * createRetryableTicket method is the recommended standard. - * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error - * @param to destination L2 contract address - * @param l2CallValue call value for retryable L2 message - * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance - * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled - * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) - * @param data ABI encoded data of L2 message - * @return unique message number of the retryable transaction - */ - function unsafeCreateRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); - - // ---------- onlyRollupOrOwner functions ---------- - - /// @notice pauses all inbox functionality - function pause() external; - - /// @notice unpauses all inbox functionality - function unpause() external; - - // ---------- initializer ---------- - - /** - * @dev function to be called one time during the inbox upgrade process - * this is used to fix the storage slots - */ - function postUpgradeInit(IBridge _bridge) external; - - function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external; -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Eth2ArbSource.sol -// License-Identifier: MIT - - - - -contract Eth2ArbSource is Initializable, LnAccessController, LnDefaultBridgeSource { - IInbox public inbox; - address public remoteBridge; - - event WithdrawMargin(address sourceToken, uint112 amount); - - receive() external payable {} - - function initialize(address _dao, address _inbox) public initializer { - inbox = IInbox(_inbox); - _initialize(_dao); - _setFeeReceiver(_dao); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) external onlyDao { - _setTokenInfo( - _sourceToken, - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals - ); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function submissionSlashFee( - uint256 baseFee, - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty, - uint256 percentIncrease - ) external view returns(uint256) { - bytes memory slashCall = _encodeSlashCall( - params, - slasher, - fee, - penalty - ); - uint256 submissionFee = inbox.calculateRetryableSubmissionFee(slashCall.length, baseFee); - return submissionFee + submissionFee * percentIncrease / 100; - } - - function submissionWithdrawFee( - uint256 baseFee, - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount, - uint256 percentIncrease - ) external view returns(uint256) { - bytes memory withdrawCall = _encodeWithdrawCall( - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - uint256 fee = inbox.calculateRetryableSubmissionFee(withdrawCall.length, baseFee); - return fee + fee * percentIncrease / 100; - } - - function _sendMessage( - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid, - bytes memory message, - uint256 prepaid - ) internal returns(uint256) { - return inbox.createRetryableTicket{ value: prepaid }( - remoteBridge, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - message - ); - } - - // this function can retry - function slashAndRemoteRelease( - TransferParameter calldata params, - bytes32 expectedTransferId, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) payable external whenNotPaused { - bytes memory slashCallMessage = _slashAndRemoteRelease( - params, - expectedTransferId - ); - _sendMessage(maxSubmissionCost, maxGas, gasPriceBid, slashCallMessage, msg.value); - } - - function requestWithdrawMargin( - address sourceToken, - uint112 amount, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) payable external whenNotPaused { - bytes memory withdrawCallMessage = _withdrawMargin( - sourceToken, - amount - ); - _sendMessage(maxSubmissionCost, maxGas, gasPriceBid, withdrawCallMessage, msg.value); - emit WithdrawMargin(sourceToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ArbTarget.sol b/helix-contract/flatten/lnv2/Eth2ArbTarget.sol deleted file mode 100644 index 3527147c..00000000 --- a/helix-contract/flatten/lnv2/Eth2ArbTarget.sol +++ /dev/null @@ -1,1923 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/11/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnDefaultBridgeTarget.sol -// License-Identifier: MIT - -contract LnDefaultBridgeTarget is LnBridgeHelper { - uint256 constant public MIN_SLASH_TIMESTAMP = 30 * 60; - - struct ProviderInfo { - uint256 margin; - // use this slash gas reserve to pay the slash fee if transfer filled but timeout - uint256 slashReserveFund; - uint64 lastExpireFillTime; - uint64 withdrawNonce; - } - - // providerKey => margin - // providerKey = hash(provider, sourceToken, targetToken) - mapping(bytes32=>ProviderInfo) public lnProviderInfos; - - // if timestamp > 0, the Transfer has been relayed or slashed - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - struct FillTransfer { - uint64 timestamp; - address slasher; - } - - // transferId => FillTransfer - mapping(bytes32 => FillTransfer) public fillTransfers; - - event TransferFilled(address provider, bytes32 transferId); - event Slash(bytes32 transferId, address provider, address token, uint256 margin, address slasher); - event MarginUpdated(address provider, address token, uint256 amount, uint64 withdrawNonce); - event SlashReserveUpdated(address provider, address token, uint256 amount); - - function depositProviderMargin( - address sourceToken, - address targetToken, - uint256 margin - ) external payable { - require(margin > 0, "invalid margin"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin + margin; - lnProviderInfos[providerKey].margin = updatedMargin; - if (targetToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), margin); - } - emit MarginUpdated(msg.sender, sourceToken, updatedMargin, providerInfo.withdrawNonce); - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) external payable { - require(params.provider == msg.sender, "invalid provider"); - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - require(expectedTransferId == transferId, "check expected transferId failed"); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - // Make sure this transfer was never filled before - require(fillTransfer.timestamp == 0, "transfer has been filled"); - - fillTransfers[transferId].timestamp = uint64(block.timestamp); - if (block.timestamp - MIN_SLASH_TIMESTAMP > params.timestamp) { - bytes32 providerKey = getDefaultProviderKey(msg.sender, params.sourceToken, params.targetToken); - lnProviderInfos[providerKey].lastExpireFillTime = uint64(block.timestamp); - } - - if (params.targetToken == address(0)) { - require(msg.value == params.amount, "lnBridgeTarget:invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - emit TransferFilled(params.provider, transferId); - } - - function depositSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external payable { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedAmount = providerInfo.slashReserveFund + amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - require(msg.value == amount, "amount invalid"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - // withdraw slash fund - // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time - function withdrawSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - require(amount <= providerInfo.slashReserveFund, "reserve not enough"); - require(block.timestamp - MIN_SLASH_TIMESTAMP >= providerInfo.lastExpireFillTime, "time not expired"); - uint256 updatedAmount = providerInfo.slashReserveFund - amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - _safeTransferNative(msg.sender, amount); - } else { - _safeTransfer(targetToken, msg.sender, amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - function _withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal { - // ensure all transfer has finished - require(lastTransferId == bytes32(0) || fillTransfers[lastTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - // all the early withdraw info ignored - require(providerInfo.withdrawNonce < withdrawNonce, "withdraw nonce expired"); - - // transfer token - require(providerInfo.margin >= amount, "margin not enough"); - uint256 updatedMargin = providerInfo.margin - amount; - lnProviderInfos[providerKey].margin = updatedMargin; - lnProviderInfos[providerKey].withdrawNonce = withdrawNonce; - - if (targetToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(targetToken, provider, amount); - } - emit MarginUpdated(provider, sourceToken, updatedMargin, withdrawNonce); - } - - function _slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal { - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - require(fillTransfer.slasher == address(0), "transfer has been slashed"); - bytes32 providerKey = getDefaultProviderKey(params.provider, params.sourceToken, params.targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin; - // transfer is not filled - if (fillTransfer.timestamp == 0) { - require(params.timestamp < block.timestamp - MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), slasher); - - // 1. transfer token to receiver - // 2. trnasfer fee and penalty to slasher - // update margin - uint256 marginCost = params.amount + fee + penalty; - require(providerInfo.margin >= marginCost, "margin not enough"); - updatedMargin = providerInfo.margin - marginCost; - lnProviderInfos[providerKey].margin = updatedMargin; - - if (params.targetToken == address(0)) { - _safeTransferNative(params.receiver, params.amount); - _safeTransferNative(slasher, fee + penalty); - } else { - _safeTransfer(params.targetToken, params.receiver, uint256(params.amount)); - _safeTransfer(params.targetToken, slasher, fee + penalty); - } - } else { - require(fillTransfer.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId].slasher = slasher; - uint112 slashRefund = penalty / 5; - // transfer slashRefund to slasher - require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); - lnProviderInfos[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; - if (params.targetToken == address(0)) { - _safeTransferNative(slasher, slashRefund); - } else { - _safeTransfer(params.targetToken, slasher, slashRefund); - } - } - emit Slash(transferId, params.provider, params.sourceToken, updatedMargin, slasher); - } -} - -// File @arbitrum/nitro-contracts/src/libraries/AddressAliasHelper.sol@v1.0.1 -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// License-Identifier: BUSL-1.1 - - -library AddressAliasHelper { - uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); - - /// @notice Utility function that converts the address in the L1 that submitted a tx to - /// the inbox to the msg.sender viewed in the L2 - /// @param l1Address the address in the L1 that triggered the tx to L2 - /// @return l2Address L2 address as viewed in msg.sender - function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { - unchecked { - l2Address = address(uint160(l1Address) + OFFSET); - } - } - - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l2Address L2 address as viewed in msg.sender - /// @return l1Address the address in the L1 that triggered the tx to L2 - function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { - unchecked { - l1Address = address(uint160(l2Address) - OFFSET); - } - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Eth2ArbTarget.sol -// License-Identifier: MIT - - - - -contract Eth2ArbTarget is Initializable, LnAccessController, LnDefaultBridgeTarget { - address public remoteBridge; - address public remoteBridgeAlias; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(msg.sender == remoteBridgeAlias, "invalid remote caller"); - _; - } - - function initialize(address dao) public initializer { - _initialize(dao); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - remoteBridgeAlias = AddressAliasHelper.applyL1ToL2Alias(remoteBridge); - } - - function setRemoteBridgeAlias(address _remoteBridgeAlias) external onlyDao { - remoteBridgeAlias = _remoteBridgeAlias; - } - - function slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external onlyRemoteBridge whenNotPaused { - _slash( - params, - slasher, - fee, - penalty - ); - } - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external onlyRemoteBridge whenNotPaused { - _withdraw(lastTransferId, withdrawNonce, provider, sourceToken, targetToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2LineaReceiveService.sol b/helix-contract/flatten/lnv2/Eth2LineaReceiveService.sol index dd94328b..53b643c0 100644 --- a/helix-contract/flatten/lnv2/Eth2LineaReceiveService.sol +++ b/helix-contract/flatten/lnv2/Eth2LineaReceiveService.sol @@ -14,10 +14,10 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; +pragma solidity ^0.8.17; // File contracts/ln/base/LnAccessController.sol // License-Identifier: MIT @@ -55,7 +55,7 @@ contract LnAccessController { operator = _operator; } - function authoriseAppCaller(address appAddress, bool enable) onlyOperator external { + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { callerWhiteList[appAddress] = enable; } @@ -64,6 +64,14 @@ contract LnAccessController { } } +// File contracts/ln/messager/interface/ILineaMessageService.sol +// License-Identifier: MIT + +interface ILineaMessageService { + function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable; + function sender() external view returns (address); +} + // File contracts/ln/interface/ILowLevelMessager.sol // License-Identifier: MIT @@ -77,14 +85,6 @@ interface ILowLevelMessageReceiver { function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; } -// File contracts/ln/messager/interface/ILineaMessageService.sol -// License-Identifier: MIT - -interface ILineaMessageService { - function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable; - function sender() external view returns (address); -} - // File contracts/ln/messager/Eth2LineaReceiveService.sol // License-Identifier: MIT @@ -110,7 +110,7 @@ contract Eth2LineaReceiveService is ILowLevelMessageReceiver, LnAccessController REMOTE_CHAINID = _remoteChainId; } - function setRemoteMessager(address _remoteMessager) onlyOperator external { + function setRemoteMessager(address _remoteMessager) onlyDao external { remoteMessager = _remoteMessager; } diff --git a/helix-contract/flatten/lnv2/Eth2LineaSendService.sol b/helix-contract/flatten/lnv2/Eth2LineaSendService.sol index d383de8c..9aa5e6b2 100644 --- a/helix-contract/flatten/lnv2/Eth2LineaSendService.sol +++ b/helix-contract/flatten/lnv2/Eth2LineaSendService.sol @@ -14,23 +14,10 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; - -// File contracts/ln/interface/ILowLevelMessager.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; -} +pragma solidity ^0.8.17; // File contracts/ln/base/LnAccessController.sol // License-Identifier: MIT @@ -68,7 +55,7 @@ contract LnAccessController { operator = _operator; } - function authoriseAppCaller(address appAddress, bool enable) onlyOperator external { + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { callerWhiteList[appAddress] = enable; } @@ -77,6 +64,19 @@ contract LnAccessController { } } +// File contracts/ln/interface/ILowLevelMessager.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/ln/messager/interface/ILineaMessageService.sol // License-Identifier: MIT @@ -104,7 +104,7 @@ contract Eth2LineaSendService is ILowLevelMessageSender, LnAccessController { REMOTE_CHAINID = _remoteChainId; } - function setRemoteMessager(address _remoteMessager) onlyOperator external { + function setRemoteMessager(address _remoteMessager) onlyDao external { remoteMessager = _remoteMessager; } diff --git a/helix-contract/flatten/lnv2/Eth2LineaSource.sol b/helix-contract/flatten/lnv2/Eth2LineaSource.sol deleted file mode 100644 index d6095e64..00000000 --- a/helix-contract/flatten/lnv2/Eth2LineaSource.sol +++ /dev/null @@ -1,2059 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/22/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File contracts/ln/interface/ILineaMessageService.sol -// License-Identifier: MIT - -interface ILineaMessageService { - function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable; - function sender() external view returns (address); -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/interface/ILnDefaultBridgeTarget.sol -// License-Identifier: MIT - - -interface ILnDefaultBridgeTarget { - function slash( - LnBridgeHelper.TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external; - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external; -} - -// File contracts/ln/base/LnDefaultBridgeSource.sol -// License-Identifier: MIT - - - -/// @title LnPositiveBridgeSource -/// @notice LnPositiveBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can send a slash request message to target chain, then force transfer from lnProvider's margin to the user. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnDefaultBridgeSource is LnBridgeHelper { - // the time(seconds) for liquidity provider to delivery message - // if timeout, slasher can work. - uint256 constant public MIN_SLASH_TIMESTAMP = 30 * 60; - // liquidity fee base rate - // liquidityFee = liquidityFeeRate / LIQUIDITY_FEE_RATE_BASE * sendAmount - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - // max transfer amount one time - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - - // provider fee is paid to liquidity node's account - // the fee is charged by the same token that user transfered - // providerFee = baseFee + liquidityFeeRate/LIQUIDITY_FEE_RATE_BASE * sendAmount - struct LnProviderFee { - uint112 baseFee; - uint8 liquidityFeeRate; - } - - struct LnProviderInfo { - LnProviderFee fee; - // we use this nonce to generate the unique withdraw id - uint64 withdrawNonce; - bytes32 lastTransferId; - } - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId or withdrawNonce updated, revert - // 2. if totalFee increase, revert - // 3. if totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 totalFee; - uint64 withdrawNonce; - } - - // lock info - // the fee and penalty is the state of the transfer confirmed - struct LockInfo { - uint112 fee; - uint112 penalty; - bool isLocked; - } - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // providerKey => provider info - mapping(bytes32=>LnProviderInfo) public lnProviders; - // transferId => lock info - mapping(bytes32=>LockInfo) public lockInfos; - - address public protocolFeeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LnProviderUpdated(address provider, address sourceToken, uint112 baseFee, uint8 liquidityfeeRate); - - // protocolFeeReceiver is the protocol fee reciever, we don't use the contract itself as the receiver - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - protocolFeeReceiver = _feeReceiver; - } - - // register or update token info, it can be only called by contract owner - // source token can only map a unique target token on target chain - function _setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) internal { - tokenInfos[_sourceToken] = TokenInfo( - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals, - true - ); - } - - // lnProvider register - // 1. set fee on source chain - // 2. deposit margin on target chain - function setProviderFee( - address sourceToken, - uint112 baseFee, - uint8 liquidityFeeRate - ) external { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderFee memory providerFee = LnProviderFee(baseFee, liquidityFeeRate); - - // we only update the field fee of the provider info - // if the provider has not been registered, then this line will register, otherwise update fee - lnProviders[providerKey].fee = providerFee; - - emit LnProviderUpdated(msg.sender, sourceToken, baseFee, liquidityFeeRate); - } - - function calculateProviderFee(LnProviderFee memory fee, uint112 amount) internal pure returns(uint256) { - return uint256(fee.baseFee) + uint256(fee.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - return providerFee + tokenInfo.protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, withdrawNonce) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(snapshot.provider, snapshot.sourceToken, tokenInfo.targetToken); - - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired:transfer"); - require(snapshot.withdrawNonce == providerInfo.withdrawNonce, "snapshot expired:withdraw"); - require(snapshot.totalFee >= providerFee + tokenInfo.protocolFee && providerFee > 0, "fee is invalid"); - - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(amount)); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - targetAmount - )); - require(!lockInfos[transferId].isLocked, "transferId exist"); - // if the transfer refund, then the fee and penalty should be given to slasher, but the protocol fee is ignored - // and we use the penalty value configure at the moment transfer confirmed - lockInfos[transferId] = LockInfo(snapshot.totalFee, tokenInfo.penaltyLnCollateral, true); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(protocolFeeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - protocolFeeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - targetAmount, - uint112(providerFee), - timestamp, - receiver); - } - - function _sourceAmountToTargetAmount( - TokenInfo memory tokenInfo, - uint256 amount - ) internal pure returns(uint112) { - uint256 targetAmount = amount * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - return uint112(targetAmount); - } - - function _slashAndRemoteRelease( - TransferParameter memory params, - bytes32 expectedTransferId - ) internal view returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "invalid timestamp"); - TokenInfo memory tokenInfo = tokenInfos[params.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(params.amount)); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - targetAmount - )); - require(expectedTransferId == transferId, "expected transfer id not match"); - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.isLocked, "lock info not match"); - uint112 targetFee = _sourceAmountToTargetAmount(tokenInfo, lockInfo.fee); - uint112 targetPenalty = _sourceAmountToTargetAmount(tokenInfo, lockInfo.penalty); - - message = _encodeSlashCall( - params, - msg.sender, - targetFee, - targetPenalty - ); - } - - function _withdrawMargin( - address sourceToken, - uint112 amount - ) internal returns(bytes memory message) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - lnProviders[providerKey].withdrawNonce = providerInfo.withdrawNonce + 1; - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, amount); - message = _encodeWithdrawCall( - providerInfo.lastTransferId, - providerInfo.withdrawNonce + 1, - msg.sender, - sourceToken, - tokenInfo.targetToken, - targetAmount - ); - } - - function _encodeSlashCall( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.slash.selector, - params, - slasher, - fee, - penalty - ); - } - - function _encodeWithdrawCall( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.withdraw.selector, - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Eth2LineaSource.sol -// License-Identifier: MIT - - - - -contract Eth2LineaSource is Initializable, LnAccessController, LnDefaultBridgeSource { - ILineaMessageService public messageService; - address public remoteBridge; - - event WithdrawMargin(address sourceToken, uint112 amount); - - receive() external payable {} - - function initialize(address _dao, address _messageService) public initializer { - messageService = ILineaMessageService(_messageService); - _initialize(_dao); - _setFeeReceiver(_dao); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) external onlyDao { - _setTokenInfo( - _sourceToken, - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals - ); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function _sendMessage( - bytes memory message, - uint256 fee - ) internal { - messageService.sendMessage{ value: fee }( - remoteBridge, - fee, - message - ); - } - - // this function can retry - function slashAndRemoteRelease( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external whenNotPaused { - bytes memory slashCallMessage = _slashAndRemoteRelease( - params, - expectedTransferId - ); - _sendMessage(slashCallMessage, msg.value); - } - - function requestWithdrawMargin( - address sourceToken, - uint112 amount - ) payable external whenNotPaused { - bytes memory withdrawCallMessage = _withdrawMargin( - sourceToken, - amount - ); - _sendMessage(withdrawCallMessage, msg.value); - emit WithdrawMargin(sourceToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2LineaTarget.sol b/helix-contract/flatten/lnv2/Eth2LineaTarget.sol deleted file mode 100644 index d2fbe310..00000000 --- a/helix-contract/flatten/lnv2/Eth2LineaTarget.sol +++ /dev/null @@ -1,1897 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/22/2023 - **/ - -pragma solidity ^0.8.10; - -// 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/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnDefaultBridgeTarget.sol -// License-Identifier: MIT - -contract LnDefaultBridgeTarget is LnBridgeHelper { - uint256 constant public MIN_SLASH_TIMESTAMP = 30 * 60; - - struct ProviderInfo { - uint256 margin; - // use this slash gas reserve to pay the slash fee if transfer filled but timeout - uint256 slashReserveFund; - uint64 lastExpireFillTime; - uint64 withdrawNonce; - } - - // providerKey => margin - // providerKey = hash(provider, sourceToken, targetToken) - mapping(bytes32=>ProviderInfo) public lnProviderInfos; - - // if timestamp > 0, the Transfer has been relayed or slashed - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - struct FillTransfer { - uint64 timestamp; - address slasher; - } - - // transferId => FillTransfer - mapping(bytes32 => FillTransfer) public fillTransfers; - - event TransferFilled(address provider, bytes32 transferId); - event Slash(bytes32 transferId, address provider, address token, uint256 margin, address slasher); - event MarginUpdated(address provider, address token, uint256 amount, uint64 withdrawNonce); - event SlashReserveUpdated(address provider, address token, uint256 amount); - - function depositProviderMargin( - address sourceToken, - address targetToken, - uint256 margin - ) external payable { - require(margin > 0, "invalid margin"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin + margin; - lnProviderInfos[providerKey].margin = updatedMargin; - if (targetToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), margin); - } - emit MarginUpdated(msg.sender, sourceToken, updatedMargin, providerInfo.withdrawNonce); - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) external payable { - require(params.provider == msg.sender, "invalid provider"); - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - require(expectedTransferId == transferId, "check expected transferId failed"); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - // Make sure this transfer was never filled before - require(fillTransfer.timestamp == 0, "transfer has been filled"); - - fillTransfers[transferId].timestamp = uint64(block.timestamp); - if (block.timestamp - MIN_SLASH_TIMESTAMP > params.timestamp) { - bytes32 providerKey = getDefaultProviderKey(msg.sender, params.sourceToken, params.targetToken); - lnProviderInfos[providerKey].lastExpireFillTime = uint64(block.timestamp); - } - - if (params.targetToken == address(0)) { - require(msg.value == params.amount, "lnBridgeTarget:invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - emit TransferFilled(params.provider, transferId); - } - - function depositSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external payable { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedAmount = providerInfo.slashReserveFund + amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - require(msg.value == amount, "amount invalid"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - // withdraw slash fund - // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time - function withdrawSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - require(amount <= providerInfo.slashReserveFund, "reserve not enough"); - require(block.timestamp - MIN_SLASH_TIMESTAMP >= providerInfo.lastExpireFillTime, "time not expired"); - uint256 updatedAmount = providerInfo.slashReserveFund - amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - _safeTransferNative(msg.sender, amount); - } else { - _safeTransfer(targetToken, msg.sender, amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - function _withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal { - // ensure all transfer has finished - require(lastTransferId == bytes32(0) || fillTransfers[lastTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - // all the early withdraw info ignored - require(providerInfo.withdrawNonce < withdrawNonce, "withdraw nonce expired"); - - // transfer token - require(providerInfo.margin >= amount, "margin not enough"); - uint256 updatedMargin = providerInfo.margin - amount; - lnProviderInfos[providerKey].margin = updatedMargin; - lnProviderInfos[providerKey].withdrawNonce = withdrawNonce; - - if (targetToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(targetToken, provider, amount); - } - emit MarginUpdated(provider, sourceToken, updatedMargin, withdrawNonce); - } - - function _slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal { - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - require(fillTransfer.slasher == address(0), "transfer has been slashed"); - bytes32 providerKey = getDefaultProviderKey(params.provider, params.sourceToken, params.targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin; - // transfer is not filled - if (fillTransfer.timestamp == 0) { - require(params.timestamp < block.timestamp - MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), slasher); - - // 1. transfer token to receiver - // 2. trnasfer fee and penalty to slasher - // update margin - uint256 marginCost = params.amount + fee + penalty; - require(providerInfo.margin >= marginCost, "margin not enough"); - updatedMargin = providerInfo.margin - marginCost; - lnProviderInfos[providerKey].margin = updatedMargin; - - if (params.targetToken == address(0)) { - _safeTransferNative(params.receiver, params.amount); - _safeTransferNative(slasher, fee + penalty); - } else { - _safeTransfer(params.targetToken, params.receiver, uint256(params.amount)); - _safeTransfer(params.targetToken, slasher, fee + penalty); - } - } else { - require(fillTransfer.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId].slasher = slasher; - uint112 slashRefund = penalty / 5; - // transfer slashRefund to slasher - require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); - lnProviderInfos[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; - if (params.targetToken == address(0)) { - _safeTransferNative(slasher, slashRefund); - } else { - _safeTransfer(params.targetToken, slasher, slashRefund); - } - } - emit Slash(transferId, params.provider, params.sourceToken, updatedMargin, slasher); - } -} - -// File contracts/ln/interface/ILineaMessageService.sol -// License-Identifier: MIT - -interface ILineaMessageService { - function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable; - function sender() external view returns (address); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Eth2LineaTarget.sol -// License-Identifier: MIT - - - - -contract Eth2LineaTarget is Initializable, LnAccessController, LnDefaultBridgeTarget { - address public remoteBridge; - address public messageService; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(ILineaMessageService(messageService).sender() == remoteBridge, "invalid remote caller"); - _; - } - - function initialize(address _dao, address _messageService) public initializer { - _initialize(_dao); - messageService = _messageService; - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external onlyRemoteBridge whenNotPaused { - _slash( - params, - slasher, - fee, - penalty - ); - } - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external onlyRemoteBridge whenNotPaused { - _withdraw(lastTransferId, withdrawNonce, provider, sourceToken, targetToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ZkSyncSource.sol b/helix-contract/flatten/lnv2/Eth2ZkSyncSource.sol deleted file mode 100644 index 168252f2..00000000 --- a/helix-contract/flatten/lnv2/Eth2ZkSyncSource.sol +++ /dev/null @@ -1,2091 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/11/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/ln/interface/IZksyncMailbox.sol -// License-Identifier: MIT - -interface IMailbox { - function requestL2Transaction( - address _contractL2, - uint256 _l2Value, - bytes calldata _calldata, - uint256 _l2GasLimit, - uint256 _l2GasPerPubdataByteLimit, - bytes[] calldata _factoryDeps, - address _refundRecipient - ) external payable returns (bytes32 canonicalTxHash); - - // this function is used to calculate the fee on L2 - function l2TransactionBaseCost( - uint256 _gasPrice, - uint256 _l2GasLimit, - uint256 _l2GasPerPubdataByteLimit - ) external view returns (uint256); -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/interface/ILnDefaultBridgeTarget.sol -// License-Identifier: MIT - - -interface ILnDefaultBridgeTarget { - function slash( - LnBridgeHelper.TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external; - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external; -} - -// File contracts/ln/base/LnDefaultBridgeSource.sol -// License-Identifier: MIT - - - -/// @title LnPositiveBridgeSource -/// @notice LnPositiveBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can send a slash request message to target chain, then force transfer from lnProvider's margin to the user. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnDefaultBridgeSource is LnBridgeHelper { - // the time(seconds) for liquidity provider to delivery message - // if timeout, slasher can work. - uint256 constant public MIN_SLASH_TIMESTAMP = 30 * 60; - // liquidity fee base rate - // liquidityFee = liquidityFeeRate / LIQUIDITY_FEE_RATE_BASE * sendAmount - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - // max transfer amount one time - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - - // provider fee is paid to liquidity node's account - // the fee is charged by the same token that user transfered - // providerFee = baseFee + liquidityFeeRate/LIQUIDITY_FEE_RATE_BASE * sendAmount - struct LnProviderFee { - uint112 baseFee; - uint8 liquidityFeeRate; - } - - struct LnProviderInfo { - LnProviderFee fee; - // we use this nonce to generate the unique withdraw id - uint64 withdrawNonce; - bytes32 lastTransferId; - } - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId or withdrawNonce updated, revert - // 2. if totalFee increase, revert - // 3. if totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 totalFee; - uint64 withdrawNonce; - } - - // lock info - // the fee and penalty is the state of the transfer confirmed - struct LockInfo { - uint112 fee; - uint112 penalty; - bool isLocked; - } - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // providerKey => provider info - mapping(bytes32=>LnProviderInfo) public lnProviders; - // transferId => lock info - mapping(bytes32=>LockInfo) public lockInfos; - - address public protocolFeeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LnProviderUpdated(address provider, address sourceToken, uint112 baseFee, uint8 liquidityfeeRate); - - // protocolFeeReceiver is the protocol fee reciever, we don't use the contract itself as the receiver - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - protocolFeeReceiver = _feeReceiver; - } - - // register or update token info, it can be only called by contract owner - // source token can only map a unique target token on target chain - function _setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) internal { - tokenInfos[_sourceToken] = TokenInfo( - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals, - true - ); - } - - // lnProvider register - // 1. set fee on source chain - // 2. deposit margin on target chain - function setProviderFee( - address sourceToken, - uint112 baseFee, - uint8 liquidityFeeRate - ) external { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderFee memory providerFee = LnProviderFee(baseFee, liquidityFeeRate); - - // we only update the field fee of the provider info - // if the provider has not been registered, then this line will register, otherwise update fee - lnProviders[providerKey].fee = providerFee; - - emit LnProviderUpdated(msg.sender, sourceToken, baseFee, liquidityFeeRate); - } - - function calculateProviderFee(LnProviderFee memory fee, uint112 amount) internal pure returns(uint256) { - return uint256(fee.baseFee) + uint256(fee.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - return providerFee + tokenInfo.protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, withdrawNonce) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(snapshot.provider, snapshot.sourceToken, tokenInfo.targetToken); - - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired:transfer"); - require(snapshot.withdrawNonce == providerInfo.withdrawNonce, "snapshot expired:withdraw"); - require(snapshot.totalFee >= providerFee + tokenInfo.protocolFee && providerFee > 0, "fee is invalid"); - - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(amount)); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - targetAmount - )); - require(!lockInfos[transferId].isLocked, "transferId exist"); - // if the transfer refund, then the fee and penalty should be given to slasher, but the protocol fee is ignored - // and we use the penalty value configure at the moment transfer confirmed - lockInfos[transferId] = LockInfo(snapshot.totalFee, tokenInfo.penaltyLnCollateral, true); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(protocolFeeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - protocolFeeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - targetAmount, - uint112(providerFee), - timestamp, - receiver); - } - - function _sourceAmountToTargetAmount( - TokenInfo memory tokenInfo, - uint256 amount - ) internal pure returns(uint112) { - uint256 targetAmount = amount * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - return uint112(targetAmount); - } - - function _slashAndRemoteRelease( - TransferParameter memory params, - bytes32 expectedTransferId - ) internal view returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "invalid timestamp"); - TokenInfo memory tokenInfo = tokenInfos[params.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(params.amount)); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - targetAmount - )); - require(expectedTransferId == transferId, "expected transfer id not match"); - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.isLocked, "lock info not match"); - uint112 targetFee = _sourceAmountToTargetAmount(tokenInfo, lockInfo.fee); - uint112 targetPenalty = _sourceAmountToTargetAmount(tokenInfo, lockInfo.penalty); - - message = _encodeSlashCall( - params, - msg.sender, - targetFee, - targetPenalty - ); - } - - function _withdrawMargin( - address sourceToken, - uint112 amount - ) internal returns(bytes memory message) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - lnProviders[providerKey].withdrawNonce = providerInfo.withdrawNonce + 1; - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, amount); - message = _encodeWithdrawCall( - providerInfo.lastTransferId, - providerInfo.withdrawNonce + 1, - msg.sender, - sourceToken, - tokenInfo.targetToken, - targetAmount - ); - } - - function _encodeSlashCall( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.slash.selector, - params, - slasher, - fee, - penalty - ); - } - - function _encodeWithdrawCall( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.withdraw.selector, - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Eth2ZkSyncSource.sol -// License-Identifier: MIT - - - - -contract Eth2ZkSyncSource is Initializable, LnAccessController, LnDefaultBridgeSource { - IMailbox public mailbox; - address public remoteBridge; - - event WithdrawMargin(address sourceToken, uint112 amount); - - receive() external payable {} - - function initialize(address _dao, address _mailbox) public initializer { - mailbox = IMailbox(_mailbox); - _initialize(_dao); - _setFeeReceiver(_dao); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) external onlyDao { - _setTokenInfo( - _sourceToken, - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals - ); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function l2Fee( - uint256 gasPrice, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) external view returns(uint256) { - return mailbox.l2TransactionBaseCost(gasPrice, l2GasLimit, l2GasPerPubdataByteLimit); - } - - function _sendMessage( - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit, - bytes memory message, - uint256 prepaid - ) internal returns(bytes32) { - return mailbox.requestL2Transaction{ value: prepaid }( - remoteBridge, - 0, - message, - l2GasLimit, - l2GasPerPubdataByteLimit, - new bytes[](0), - msg.sender - ); - } - - // this function can retry - function slashAndRemoteRelease( - TransferParameter calldata params, - bytes32 expectedTransferId, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) payable external whenNotPaused { - bytes memory slashCallMessage = _slashAndRemoteRelease( - params, - expectedTransferId - ); - _sendMessage(l2GasLimit, l2GasPerPubdataByteLimit, slashCallMessage, msg.value); - } - - function requestWithdrawMargin( - address sourceToken, - uint112 amount, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) payable external whenNotPaused { - bytes memory withdrawCallMessage = _withdrawMargin( - sourceToken, - amount - ); - _sendMessage(l2GasLimit, l2GasPerPubdataByteLimit, withdrawCallMessage, msg.value); - emit WithdrawMargin(sourceToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ZkSyncTarget.sol b/helix-contract/flatten/lnv2/Eth2ZkSyncTarget.sol deleted file mode 100644 index 8a74b49d..00000000 --- a/helix-contract/flatten/lnv2/Eth2ZkSyncTarget.sol +++ /dev/null @@ -1,1894 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/11/2023 - **/ - -pragma solidity ^0.8.10; - -// 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/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnDefaultBridgeTarget.sol -// License-Identifier: MIT - -contract LnDefaultBridgeTarget is LnBridgeHelper { - uint256 constant public MIN_SLASH_TIMESTAMP = 30 * 60; - - struct ProviderInfo { - uint256 margin; - // use this slash gas reserve to pay the slash fee if transfer filled but timeout - uint256 slashReserveFund; - uint64 lastExpireFillTime; - uint64 withdrawNonce; - } - - // providerKey => margin - // providerKey = hash(provider, sourceToken, targetToken) - mapping(bytes32=>ProviderInfo) public lnProviderInfos; - - // if timestamp > 0, the Transfer has been relayed or slashed - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - struct FillTransfer { - uint64 timestamp; - address slasher; - } - - // transferId => FillTransfer - mapping(bytes32 => FillTransfer) public fillTransfers; - - event TransferFilled(address provider, bytes32 transferId); - event Slash(bytes32 transferId, address provider, address token, uint256 margin, address slasher); - event MarginUpdated(address provider, address token, uint256 amount, uint64 withdrawNonce); - event SlashReserveUpdated(address provider, address token, uint256 amount); - - function depositProviderMargin( - address sourceToken, - address targetToken, - uint256 margin - ) external payable { - require(margin > 0, "invalid margin"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin + margin; - lnProviderInfos[providerKey].margin = updatedMargin; - if (targetToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), margin); - } - emit MarginUpdated(msg.sender, sourceToken, updatedMargin, providerInfo.withdrawNonce); - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) external payable { - require(params.provider == msg.sender, "invalid provider"); - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - require(expectedTransferId == transferId, "check expected transferId failed"); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - // Make sure this transfer was never filled before - require(fillTransfer.timestamp == 0, "transfer has been filled"); - - fillTransfers[transferId].timestamp = uint64(block.timestamp); - if (block.timestamp - MIN_SLASH_TIMESTAMP > params.timestamp) { - bytes32 providerKey = getDefaultProviderKey(msg.sender, params.sourceToken, params.targetToken); - lnProviderInfos[providerKey].lastExpireFillTime = uint64(block.timestamp); - } - - if (params.targetToken == address(0)) { - require(msg.value == params.amount, "lnBridgeTarget:invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - emit TransferFilled(params.provider, transferId); - } - - function depositSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external payable { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedAmount = providerInfo.slashReserveFund + amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - require(msg.value == amount, "amount invalid"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - // withdraw slash fund - // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time - function withdrawSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - require(amount <= providerInfo.slashReserveFund, "reserve not enough"); - require(block.timestamp - MIN_SLASH_TIMESTAMP >= providerInfo.lastExpireFillTime, "time not expired"); - uint256 updatedAmount = providerInfo.slashReserveFund - amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - _safeTransferNative(msg.sender, amount); - } else { - _safeTransfer(targetToken, msg.sender, amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - function _withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal { - // ensure all transfer has finished - require(lastTransferId == bytes32(0) || fillTransfers[lastTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - // all the early withdraw info ignored - require(providerInfo.withdrawNonce < withdrawNonce, "withdraw nonce expired"); - - // transfer token - require(providerInfo.margin >= amount, "margin not enough"); - uint256 updatedMargin = providerInfo.margin - amount; - lnProviderInfos[providerKey].margin = updatedMargin; - lnProviderInfos[providerKey].withdrawNonce = withdrawNonce; - - if (targetToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(targetToken, provider, amount); - } - emit MarginUpdated(provider, sourceToken, updatedMargin, withdrawNonce); - } - - function _slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal { - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - require(fillTransfer.slasher == address(0), "transfer has been slashed"); - bytes32 providerKey = getDefaultProviderKey(params.provider, params.sourceToken, params.targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin; - // transfer is not filled - if (fillTransfer.timestamp == 0) { - require(params.timestamp < block.timestamp - MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), slasher); - - // 1. transfer token to receiver - // 2. trnasfer fee and penalty to slasher - // update margin - uint256 marginCost = params.amount + fee + penalty; - require(providerInfo.margin >= marginCost, "margin not enough"); - updatedMargin = providerInfo.margin - marginCost; - lnProviderInfos[providerKey].margin = updatedMargin; - - if (params.targetToken == address(0)) { - _safeTransferNative(params.receiver, params.amount); - _safeTransferNative(slasher, fee + penalty); - } else { - _safeTransfer(params.targetToken, params.receiver, uint256(params.amount)); - _safeTransfer(params.targetToken, slasher, fee + penalty); - } - } else { - require(fillTransfer.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId].slasher = slasher; - uint112 slashRefund = penalty / 5; - // transfer slashRefund to slasher - require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); - lnProviderInfos[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; - if (params.targetToken == address(0)) { - _safeTransferNative(slasher, slashRefund); - } else { - _safeTransfer(params.targetToken, slasher, slashRefund); - } - } - emit Slash(transferId, params.provider, params.sourceToken, updatedMargin, slasher); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Eth2ZkSyncTarget.sol -// License-Identifier: MIT - - - -contract Eth2ZkSyncTarget is Initializable, LnAccessController, LnDefaultBridgeTarget { - uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); - address public remoteBridge; - address public remoteBridgeAlias; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(msg.sender == remoteBridgeAlias, "invalid remote caller"); - _; - } - - function initialize(address dao) public initializer { - _initialize(dao); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - // l1 address to l2 address - remoteBridgeAlias = address(uint160(_remoteBridge) + offset); - } - - function setRemoteBridgeAlias(address _remoteBridgeAlias) external onlyDao { - remoteBridgeAlias = _remoteBridgeAlias; - } - - function slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external onlyRemoteBridge whenNotPaused { - _slash( - params, - slasher, - fee, - penalty - ); - } - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external onlyRemoteBridge whenNotPaused { - _withdraw(lastTransferId, withdrawNonce, provider, sourceToken, targetToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/LayerZeroBridge.sol b/helix-contract/flatten/lnv2/LayerZeroBridge.sol deleted file mode 100644 index 834dfd74..00000000 --- a/helix-contract/flatten/lnv2/LayerZeroBridge.sol +++ /dev/null @@ -1,2388 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/25/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnDefaultBridgeTarget.sol -// License-Identifier: MIT - -contract LnDefaultBridgeTarget is LnBridgeHelper { - uint256 constant private MIN_SLASH_TIMESTAMP = 30 * 60; - - struct ProviderInfo { - uint256 margin; - // use this slash gas reserve to pay the slash fee if transfer filled but timeout - uint256 slashReserveFund; - uint64 lastExpireFillTime; - uint64 withdrawNonce; - } - - // providerKey => margin - // providerKey = hash(provider, sourceToken, targetToken) - mapping(bytes32=>ProviderInfo) public lnProviderInfos; - - // if timestamp > 0, the Transfer has been relayed or slashed - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - struct FillTransfer { - uint64 timestamp; - address slasher; - } - - // transferId => FillTransfer - mapping(bytes32 => FillTransfer) public fillTransfers; - - event TransferFilled(address provider, bytes32 transferId); - event Slash(bytes32 transferId, address provider, address token, uint256 margin, address slasher); - event MarginUpdated(address provider, address token, uint256 amount, uint64 withdrawNonce); - event SlashReserveUpdated(address provider, address token, uint256 amount); - - function depositProviderMargin( - address sourceToken, - address targetToken, - uint256 margin - ) external payable { - require(margin > 0, "invalid margin"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin + margin; - lnProviderInfos[providerKey].margin = updatedMargin; - if (targetToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), margin); - } - emit MarginUpdated(msg.sender, sourceToken, updatedMargin, providerInfo.withdrawNonce); - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) external payable { - require(params.provider == msg.sender, "invalid provider"); - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - require(expectedTransferId == transferId, "check expected transferId failed"); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - // Make sure this transfer was never filled before - require(fillTransfer.timestamp == 0, "transfer has been filled"); - - fillTransfers[transferId].timestamp = uint64(block.timestamp); - if (block.timestamp - MIN_SLASH_TIMESTAMP > params.timestamp) { - bytes32 providerKey = getDefaultProviderKey(msg.sender, params.sourceToken, params.targetToken); - lnProviderInfos[providerKey].lastExpireFillTime = uint64(block.timestamp); - } - - if (params.targetToken == address(0)) { - require(msg.value == params.amount, "lnBridgeTarget:invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - emit TransferFilled(params.provider, transferId); - } - - function depositSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external payable { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedAmount = providerInfo.slashReserveFund + amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - require(msg.value == amount, "amount invalid"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - // withdraw slash fund - // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time - function withdrawSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - require(amount <= providerInfo.slashReserveFund, "reserve not enough"); - require(block.timestamp - MIN_SLASH_TIMESTAMP >= providerInfo.lastExpireFillTime, "time not expired"); - uint256 updatedAmount = providerInfo.slashReserveFund - amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - _safeTransferNative(msg.sender, amount); - } else { - _safeTransfer(targetToken, msg.sender, amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - function _withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal { - // ensure all transfer has finished - require(lastTransferId == bytes32(0) || fillTransfers[lastTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - // all the early withdraw info ignored - require(providerInfo.withdrawNonce < withdrawNonce, "withdraw nonce expired"); - - // transfer token - require(providerInfo.margin >= amount, "margin not enough"); - uint256 updatedMargin = providerInfo.margin - amount; - lnProviderInfos[providerKey].margin = updatedMargin; - lnProviderInfos[providerKey].withdrawNonce = withdrawNonce; - - if (targetToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(targetToken, provider, amount); - } - emit MarginUpdated(provider, sourceToken, updatedMargin, withdrawNonce); - } - - function _slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal { - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - require(fillTransfer.slasher == address(0), "transfer has been slashed"); - bytes32 providerKey = getDefaultProviderKey(params.provider, params.sourceToken, params.targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin; - // transfer is not filled - if (fillTransfer.timestamp == 0) { - require(params.timestamp < block.timestamp - MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), slasher); - - // 1. transfer token to receiver - // 2. trnasfer fee and penalty to slasher - // update margin - uint256 marginCost = params.amount + fee + penalty; - require(providerInfo.margin >= marginCost, "margin not enough"); - updatedMargin = providerInfo.margin - marginCost; - lnProviderInfos[providerKey].margin = updatedMargin; - - if (params.targetToken == address(0)) { - _safeTransferNative(params.receiver, params.amount); - _safeTransferNative(slasher, fee + penalty); - } else { - _safeTransfer(params.targetToken, params.receiver, uint256(params.amount)); - _safeTransfer(params.targetToken, slasher, fee + penalty); - } - } else { - require(fillTransfer.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId].slasher = slasher; - uint112 slashRefund = penalty / 5; - // transfer slashRefund to slasher - require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); - lnProviderInfos[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; - if (params.targetToken == address(0)) { - _safeTransferNative(slasher, slashRefund); - } else { - _safeTransfer(params.targetToken, slasher, slashRefund); - } - } - emit Slash(transferId, params.provider, params.sourceToken, updatedMargin, slasher); - } -} - -// File contracts/ln/interface/ILnDefaultBridgeTarget.sol -// License-Identifier: MIT - - -interface ILnDefaultBridgeTarget { - function slash( - LnBridgeHelper.TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external; - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external; -} - -// File contracts/ln/base/LnDefaultBridgeSource.sol -// License-Identifier: MIT - - - -/// @title LnPositiveBridgeSource -/// @notice LnPositiveBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can send a slash request message to target chain, then force transfer from lnProvider's margin to the user. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnDefaultBridgeSource is LnBridgeHelper { - // the time(seconds) for liquidity provider to delivery message - // if timeout, slasher can work. - uint256 constant private MIN_SLASH_TIMESTAMP = 30 * 60; - // liquidity fee base rate - // liquidityFee = liquidityFeeRate / LIQUIDITY_FEE_RATE_BASE * sendAmount - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - // max transfer amount one time - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - - // provider fee is paid to liquidity node's account - // the fee is charged by the same token that user transfered - // providerFee = baseFee + liquidityFeeRate/LIQUIDITY_FEE_RATE_BASE * sendAmount - struct LnProviderFee { - uint112 baseFee; - uint8 liquidityFeeRate; - } - - struct LnProviderInfo { - LnProviderFee fee; - // we use this nonce to generate the unique withdraw id - uint64 withdrawNonce; - bytes32 lastTransferId; - } - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId or withdrawNonce updated, revert - // 2. if totalFee increase, revert - // 3. if totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 totalFee; - uint64 withdrawNonce; - } - - // lock info - // the fee and penalty is the state of the transfer confirmed - struct LockInfo { - uint112 fee; - uint112 penalty; - bool isLocked; - } - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // providerKey => provider info - mapping(bytes32=>LnProviderInfo) public lnProviders; - // transferId => lock info - mapping(bytes32=>LockInfo) public lockInfos; - - address public protocolFeeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LnProviderUpdated(address provider, address sourceToken, uint112 baseFee, uint8 liquidityfeeRate); - - // protocolFeeReceiver is the protocol fee reciever, we don't use the contract itself as the receiver - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - protocolFeeReceiver = _feeReceiver; - } - - // register or update token info, it can be only called by contract owner - // source token can only map a unique target token on target chain - function _setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) internal { - tokenInfos[_sourceToken] = TokenInfo( - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals, - true - ); - } - - // lnProvider register - // 1. set fee on source chain - // 2. deposit margin on target chain - function setProviderFee( - address sourceToken, - uint112 baseFee, - uint8 liquidityFeeRate - ) external { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderFee memory providerFee = LnProviderFee(baseFee, liquidityFeeRate); - - // we only update the field fee of the provider info - // if the provider has not been registered, then this line will register, otherwise update fee - lnProviders[providerKey].fee = providerFee; - - emit LnProviderUpdated(msg.sender, sourceToken, baseFee, liquidityFeeRate); - } - - function calculateProviderFee(LnProviderFee memory fee, uint112 amount) internal pure returns(uint256) { - return uint256(fee.baseFee) + uint256(fee.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - return providerFee + tokenInfo.protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, withdrawNonce) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(snapshot.provider, snapshot.sourceToken, tokenInfo.targetToken); - - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired:transfer"); - require(snapshot.withdrawNonce == providerInfo.withdrawNonce, "snapshot expired:withdraw"); - require(snapshot.totalFee >= providerFee + tokenInfo.protocolFee && providerFee > 0, "fee is invalid"); - - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(amount)); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - targetAmount - )); - require(!lockInfos[transferId].isLocked, "transferId exist"); - // if the transfer refund, then the fee and penalty should be given to slasher, but the protocol fee is ignored - // and we use the penalty value configure at the moment transfer confirmed - lockInfos[transferId] = LockInfo(snapshot.totalFee, tokenInfo.penaltyLnCollateral, true); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(protocolFeeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - protocolFeeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - targetAmount, - uint112(providerFee), - timestamp, - receiver); - } - - function _sourceAmountToTargetAmount( - TokenInfo memory tokenInfo, - uint256 amount - ) internal pure returns(uint112) { - uint256 targetAmount = amount * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - return uint112(targetAmount); - } - - function _slashAndRemoteRelease( - TransferParameter memory params, - bytes32 expectedTransferId - ) internal view returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "invalid timestamp"); - TokenInfo memory tokenInfo = tokenInfos[params.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(params.amount)); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - targetAmount - )); - require(expectedTransferId == transferId, "expected transfer id not match"); - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.isLocked, "lock info not match"); - uint112 targetFee = _sourceAmountToTargetAmount(tokenInfo, lockInfo.fee); - uint112 targetPenalty = _sourceAmountToTargetAmount(tokenInfo, lockInfo.penalty); - - message = _encodeSlashCall( - params, - msg.sender, - targetFee, - targetPenalty - ); - } - - function _withdrawMargin( - address sourceToken, - uint112 amount - ) internal returns(bytes memory message) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - lnProviders[providerKey].withdrawNonce = providerInfo.withdrawNonce + 1; - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, amount); - message = _encodeWithdrawCall( - providerInfo.lastTransferId, - providerInfo.withdrawNonce + 1, - msg.sender, - sourceToken, - tokenInfo.targetToken, - targetAmount - ); - } - - function _encodeSlashCall( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) public pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.slash.selector, - params, - slasher, - fee, - penalty - ); - } - - function _encodeWithdrawCall( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) public pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.withdraw.selector, - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - } -} - -// File contracts/ln/interface/ILayerZeroEndpoint.sol -// License-Identifier: MIT - -interface ILayerZeroEndpoint { - function send( - uint16 _dstChainId, - bytes calldata _destination, - bytes calldata _payload, - address payable _refundAddress, - address _zroPaymentAddress, - bytes calldata _adapterParams - ) external payable; - - function estimateFees( - uint16 _dstChainId, - address _userApplication, - bytes calldata _payload, - bool _payInZRO, - bytes calldata _adapterParam - ) external view returns (uint nativeFee, uint zroFee); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/LayerZeroBridge.sol -// License-Identifier: MIT - - - - - -contract LayerZeroBridge is Initializable, LnAccessController, LnDefaultBridgeSource, LnDefaultBridgeTarget { - ILayerZeroEndpoint public endpoint; - address public remoteBridge; - bytes32 public trustedRemote; - uint16 public remoteChainId; - - event WithdrawMargin(address sourceToken, uint112 amount); - event CallResult(bytes srcAddress, bool successed); - - receive() external payable {} - - modifier onlyRemoteBridge(bytes calldata srcAddress) { - require(msg.sender == address(endpoint), "invalid caller"); - require(trustedRemote == keccak256(srcAddress), "invalid remote caller"); - _; - } - - function initialize(address _dao, address _endpoint, uint16 _remoteChainId) public initializer { - _initialize(_dao); - endpoint = ILayerZeroEndpoint(_endpoint); - _setFeeReceiver(_dao); - remoteChainId = _remoteChainId; - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - trustedRemote = keccak256(abi.encodePacked(_remoteBridge, address(this))); - } - - function setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) external onlyDao { - _setTokenInfo( - _sourceToken, - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals - ); - } - - function estimateSlashFee( - TransferParameter calldata params - ) external view returns(uint256 nativeFee, uint256 zroFee) { - bytes memory slashCallMessage = _encodeSlashCall( - params, - msg.sender, - 0, - 0 - ); - return endpoint.estimateFees( - remoteChainId, - remoteBridge, - slashCallMessage, - false, - bytes("") - ); - } - - function estimateWithdrawFee( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external view returns(uint256 nativeFee, uint256 zroFee) { - bytes memory withdrawCallMessage = _encodeWithdrawCall( - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - return endpoint.estimateFees( - remoteChainId, - remoteBridge, - withdrawCallMessage, - false, - bytes("") - ); - } - - function _sendMessage( - bytes memory message, - uint256 prepaid - ) internal { - bytes memory destination = abi.encodePacked( - remoteBridge, - address(this) - ); - endpoint.send{ value: prepaid }( - remoteChainId, - destination, - message, - payable(msg.sender), - // zro payment, future parameter - address(0x0), - bytes("") - ); - } - - function slashAndRemoteRelease( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external whenNotPaused { - bytes memory slashCallMessage = _slashAndRemoteRelease( - params, - expectedTransferId - ); - _sendMessage(slashCallMessage, msg.value); - } - - function requestWithdrawMargin( - address sourceToken, - uint112 amount - ) payable external whenNotPaused { - bytes memory withdrawCallMessage = _withdrawMargin( - sourceToken, - amount - ); - _sendMessage(withdrawCallMessage, msg.value); - emit WithdrawMargin(sourceToken, amount); - } - - function lzReceive( - uint16 _srcChainId, - bytes calldata _srcAddress, - uint64, //nonce unused - bytes calldata _payload) onlyRemoteBridge(_srcAddress) whenNotPaused external { - require(_srcChainId == remoteChainId, "invalid src chainid"); - // call - (bool success,) = address(this).call(_payload); - // don't revert to prevent message block - emit CallResult(_srcAddress, success); - } - - function slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external { - require(msg.sender == address(this), "only self"); - _slash( - params, - slasher, - fee, - penalty - ); - } - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external { - require(msg.sender == address(this), "only self"); - _withdraw(lastTransferId, withdrawNonce, provider, sourceToken, targetToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/LayerZeroMessager.sol b/helix-contract/flatten/lnv2/LayerZeroMessager.sol index 5bfc81f3..577b0a99 100644 --- a/helix-contract/flatten/lnv2/LayerZeroMessager.sol +++ b/helix-contract/flatten/lnv2/LayerZeroMessager.sol @@ -14,10 +14,23 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; +pragma solidity ^0.8.17; + +// File contracts/ln/interface/ILowLevelMessager.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/ln/base/LnAccessController.sol // License-Identifier: MIT @@ -55,7 +68,7 @@ contract LnAccessController { operator = _operator; } - function authoriseAppCaller(address appAddress, bool enable) onlyOperator external { + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { callerWhiteList[appAddress] = enable; } @@ -64,19 +77,6 @@ contract LnAccessController { } } -// File contracts/ln/interface/ILowLevelMessager.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/ln/messager/interface/ILayerZeroEndpoint.sol // License-Identifier: MIT @@ -136,7 +136,7 @@ contract LayerZeroMessager is LnAccessController { _; } - function setRemoteMessager(uint256 _appRemoteChainId, uint16 _lzRemoteChainId, address _remoteMessager) onlyOperator external { + function setRemoteMessager(uint256 _appRemoteChainId, uint16 _lzRemoteChainId, address _remoteMessager) onlyDao external { remoteMessagers[_appRemoteChainId] = RemoteMessager(_lzRemoteChainId, _remoteMessager); trustedRemotes[_lzRemoteChainId] = keccak256(abi.encodePacked(_remoteMessager, address(this))); } diff --git a/helix-contract/flatten/lnv2/Linea2EthSource.sol b/helix-contract/flatten/lnv2/Linea2EthSource.sol deleted file mode 100644 index 1113d1f3..00000000 --- a/helix-contract/flatten/lnv2/Linea2EthSource.sol +++ /dev/null @@ -1,2031 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/22/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// 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/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnOppositeBridgeSource.sol -// License-Identifier: MIT - - -/// @title LnBridgeSource -/// @notice LnBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can paid for relayer and slash the transfer, then request slash from lnProvider's margin. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnOppositeBridgeSource is LnBridgeHelper { - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - // the Liquidity Node provider info - // Liquidity Node need register first - struct LnProviderConfigure { - uint112 margin; - uint112 baseFee; - // liquidityFeeRate / 100,000 * amount = liquidityFee - // the max liquidity fee rate is 0.255% - uint8 liquidityFeeRate; - } - struct LnProviderInfo { - LnProviderConfigure config; - bool pause; - bytes32 lastTransferId; - } - - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId updated, revert - // 2. if margin decrease or totalFee increase, revert - // 3. if margin increase or totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 depositedMargin; - uint112 totalFee; - } - // registered token info - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // registered lnProviders - mapping(bytes32=>LnProviderInfo) public lnProviders; - // each time cross chain transfer, amount and fee can't be larger than type(uint112).max - struct LockInfo { - // amount + providerFee + penaltyLnCollateral - // the Indexer should be care about this value, it will frozen lnProvider's margin when the transfer not finished. - // and when the slasher slash success, this amount of token will be transfer from lnProvider's margin to slasher. - uint112 amountWithFeeAndPenalty; - bool hasSlashed; - } - // key: transferId = hash(proviousTransferId, timestamp, targetToken, receiver, targetAmount) - // * `proviousTransferId` is used to ensure the continuous of the transfer - // * `timestamp` is the block.timestmap to judge timeout on target chain(here we support source and target chain has the same world clock) - // * `targetToken`, `receiver` and `targetAmount` are used on target chain to transfer target token. - mapping(bytes32 => LockInfo) public lockInfos; - address public feeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LiquidityWithdrawn(address provider, address token, uint112 amount); - event Slash(bytes32 transferId, address provider, address token, uint112 margin, address slasher); - // relayer - event LnProviderUpdated(address provider, address token, uint112 margin, uint112 baseFee, uint8 liquidityfeeRate); - - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - feeReceiver = _feeReceiver; - } - - function _updateProtocolFee(address _token, uint112 _protocolFee) internal { - require(tokenInfos[_token].isRegistered, "token not registered"); - tokenInfos[_token].protocolFee = _protocolFee; - } - - function _updatePenaltyLnCollateral(address _token, uint112 _penaltyLnCollateral) internal { - require(tokenInfos[_token].isRegistered, "token not registered"); - tokenInfos[_token].penaltyLnCollateral = _penaltyLnCollateral; - } - - function providerPause(address sourceToken) external { - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - lnProviders[providerKey].pause = true; - } - - function providerUnpause(address sourceToken) external { - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - lnProviders[providerKey].pause = false; - } - - // lnProvider can register or update its configure by using this function - // * `margin` is the increased value of the deposited margin - function updateProviderFeeAndMargin( - address sourceToken, - uint112 margin, - uint112 baseFee, - uint8 liquidityFeeRate - ) external payable { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token is not registered"); - - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - - LnProviderConfigure memory config = LnProviderConfigure( - // the margin can be only increased here - margin + providerInfo.config.margin, - baseFee, - liquidityFeeRate - ); - - lnProviders[providerKey].config = config; - - if (sourceToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - if (margin > 0) { - _safeTransferFrom(sourceToken, msg.sender, address(this), margin); - } - } - emit LnProviderUpdated(msg.sender, sourceToken, config.margin, baseFee, liquidityFeeRate); - } - - function _registerToken( - address sourceToken, - address targetToken, - uint112 protocolFee, - uint112 penaltyLnCollateral, - uint8 sourceDecimals, - uint8 targetDecimals - ) internal { - tokenInfos[sourceToken] = TokenInfo( - targetToken, - protocolFee, - penaltyLnCollateral, - sourceDecimals, - targetDecimals, - true - ); - } - - function calculateProviderFee(LnProviderConfigure memory config, uint112 amount) internal pure returns(uint256) { - return uint256(config.baseFee) + uint256(config.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - // providerFee = provider.baseFee + provider.liquidityFeeRate * amount - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - bytes32 providerKey = getProviderKey(provider, sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.config, amount); - return providerFee + tokenInfos[sourceToken].protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, margin) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - bytes32 providerKey = getProviderKey(snapshot.provider, snapshot.sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - - require(!providerInfo.pause, "provider paused"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - - uint256 providerFee = calculateProviderFee(providerInfo.config, amount); - - // Note: this requirement is not enough to ensure that the lnProvider's margin is enough because there maybe some frozen margins in other transfers - require(providerInfo.config.margin >= amount + tokenInfo.penaltyLnCollateral + uint112(providerFee), "amount not valid"); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired"); - require(snapshot.totalFee >= tokenInfo.protocolFee + providerFee, "fee is invalid"); - require(snapshot.depositedMargin <= providerInfo.config.margin, "margin updated"); - - uint256 targetAmount = uint256(amount) * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - uint112(targetAmount))); - require(lockInfos[transferId].amountWithFeeAndPenalty == 0, "transferId exist"); - lockInfos[transferId] = LockInfo(amount + tokenInfo.penaltyLnCollateral + uint112(providerFee), false); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(feeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - feeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - amount, - uint112(providerFee), - timestamp, - receiver); - } - - // this slash is called by remote message - // the token should be sent to the slasher who slash and finish the transfer on target chain. - // latestSlashTransferId is the latest slashed transfer trusted from the target chain, and the current slash transfer cannot be executed before the latestSlash transfer. - // after slash, the margin of lnProvider need to be updated - function _slash( - bytes32 latestSlashTransferId, - bytes32 transferId, - address sourceToken, - address provider, - address slasher - ) internal { - // check lastTransfer - // ensure last slash transfer(checked on target chain) has been slashed - LockInfo memory lastLockInfo = lockInfos[latestSlashTransferId]; - require(lastLockInfo.hasSlashed || latestSlashTransferId == INIT_SLASH_TRANSFER_ID, "latest slash transfer invalid"); - LockInfo memory lockInfo = lockInfos[transferId]; - - // ensure transfer exist and not slashed yet - require(!lockInfo.hasSlashed, "transfer has been slashed"); - require(lockInfo.amountWithFeeAndPenalty > 0, "lnBridgeSource:invalid transferId"); - - bytes32 providerKey = getProviderKey(provider, sourceToken); - - LnProviderInfo memory lnProvider = lnProviders[providerKey]; - lockInfos[transferId].hasSlashed = true; - // transfer token to the slasher - uint256 slashAmount = lockInfo.amountWithFeeAndPenalty; - require(lnProvider.config.margin >= slashAmount, "margin not enough"); - uint112 updatedMargin = lnProvider.config.margin - uint112(slashAmount); - lnProviders[providerKey].config.margin = updatedMargin; - - if (sourceToken == address(0)) { - _safeTransferNative(slasher, slashAmount); - } else { - _safeTransfer(sourceToken, slasher, slashAmount); - } - - emit Slash(transferId, provider, sourceToken, updatedMargin, slasher); - } - - // lastTransfer is the latest slash transfer, all transfer must be relayed or slashed - // if user use the snapshot before this transaction to send cross-chain transfer, it should be reverted because this `_withdrawMargin` will decrease margin. - function _withdrawMargin( - bytes32 latestSlashTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) internal { - // check the latest slash transfer - // ensure latest slash tranfer(verified on target chain) has been slashed on source chain - LockInfo memory lastRefundLockInfo = lockInfos[latestSlashTransferId]; - require(lastRefundLockInfo.hasSlashed || latestSlashTransferId == INIT_SLASH_TRANSFER_ID, "latest slash transfer invalid"); - - // use this condition to ensure that the withdraw message is sent by the provider - // the parameter provider is the message sender of this remote withdraw call - bytes32 providerKey = getProviderKey(provider, sourceToken); - LnProviderInfo memory lnProvider = lnProviders[providerKey]; - - // ensure all transfer has finished - require(lnProvider.lastTransferId == lastTransferId, "invalid last transferid"); - require(lnProvider.config.margin >= amount, "margin not enough"); - uint112 updatedMargin = lnProvider.config.margin - amount; - lnProviders[providerKey].config.margin = updatedMargin; - if (sourceToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(sourceToken, provider, amount); - } - emit LiquidityWithdrawn(provider, sourceToken, updatedMargin); - } -} - -// File contracts/ln/interface/ILineaMessageService.sol -// License-Identifier: MIT - -interface ILineaMessageService { - function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable; - function sender() external view returns (address); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Linea2EthSource.sol -// License-Identifier: MIT - - - - -contract Linea2EthSource is Initializable, LnAccessController, LnOppositeBridgeSource { - address public remoteBridge; - // linea message service address - address public messageService; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(ILineaMessageService(messageService).sender() == remoteBridge, "invalid remote caller"); - _; - } - - function initialize(address _dao, address _messageService) public initializer { - _initialize(_dao); - _setFeeReceiver(_dao); - messageService = _messageService; - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function updateProtocolFee(address token, uint112 _protocolFee) external onlyDao { - _updateProtocolFee(token, _protocolFee); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function registerToken( - address sourceToken, - address targetToken, - uint112 protocolFee, - uint112 penaltyLnCollateral, - uint8 sourceDecimals, - uint8 targetDecimals - ) external onlyOperator { - _registerToken(sourceToken, targetToken, protocolFee, penaltyLnCollateral, sourceDecimals, targetDecimals); - } - - function slash( - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) external onlyRemoteBridge whenNotPaused { - _slash(latestSlashTransferId, transferId, sourceToken, provider, slasher); - } - - function withdrawMargin( - bytes32 latestSlashTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) external onlyRemoteBridge whenNotPaused { - _withdrawMargin(latestSlashTransferId, lastTransferId, provider, sourceToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Linea2EthTarget.sol b/helix-contract/flatten/lnv2/Linea2EthTarget.sol deleted file mode 100644 index e9ab33b3..00000000 --- a/helix-contract/flatten/lnv2/Linea2EthTarget.sol +++ /dev/null @@ -1,1897 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/22/2023 - **/ - -pragma solidity ^0.8.10; - -// 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 @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// File contracts/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File contracts/ln/interface/ILineaMessageService.sol -// License-Identifier: MIT - -interface ILineaMessageService { - function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable; - function sender() external view returns (address); -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/interface/ILnOppositeBridgeSource.sol -// License-Identifier: MIT - - -interface ILnOppositeBridgeSource { - function slash( - bytes32 lastRefundTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) external; - - function withdrawMargin( - bytes32 lastRefundTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) external; -} - -// File contracts/ln/base/LnOppositeBridgeTarget.sol -// License-Identifier: MIT - - -contract LnOppositeBridgeTarget is LnBridgeHelper { - uint256 constant public MIN_REFUND_TIMESTAMP = 30 * 60; - - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - // if there is no slash transfer before, then it's latestSlashTransferId is assigned by INIT_SLASH_TRANSFER_ID, a special flag - struct SlashInfo { - address provider; - address sourceToken; - address slasher; - } - - // transferId => latest slash transfer Id - mapping(bytes32 => bytes32) public fillTransfers; - // transferId => Slash info - mapping(bytes32 => SlashInfo) public slashInfos; - - event TransferFilled(bytes32 transferId, address slasher); - - // if slasher is nonzero, then it's a slash fill transfer - function _checkPreviousAndFillTransfer( - bytes32 transferId, - bytes32 previousTransferId - ) internal { - // the first fill transfer, we fill the INIT_SLASH_TRANSFER_ID as the latest slash transferId - if (previousTransferId == bytes32(0)) { - fillTransfers[transferId] = INIT_SLASH_TRANSFER_ID; - } else { - // Find the previous slash fill, it is a slash fill if the slasher is not zero address. - bytes32 previousLatestSlashTransferId = fillTransfers[previousTransferId]; - require(previousLatestSlashTransferId != bytes32(0), "previous fill not exist"); - - SlashInfo memory previousSlashInfo = slashInfos[previousTransferId]; - // we use latestSlashTransferId to store the latest slash transferId - // if previous.slasher != 0, then previous is slashed - // if previous.slasher == 0, then previous is not slashed - bytes32 latestSlashTransferId = previousSlashInfo.slasher != address(0) ? previousTransferId : previousLatestSlashTransferId; - - fillTransfers[transferId] = latestSlashTransferId; - } - } - - // fill transfer - // 1. if transfer is not slashed or relayed, LnProvider relay message to fill the transfer, and the transfer finished on target chain - // 2. if transfer is timeout and not processed, slasher(any account) can fill the transfer and request slash - // if it's filled by slasher, we store the address of the slasher - // expectedTransferId used to ensure the parameter is the same as on source chain - // some cases - // 1) If transferId is not exist on source chain, it'll be rejected by source chain when shashed. - // 2) If transferId exist on source chain. We have the same hash process on source and target chain, so the previousTransferId is trusted. - // 2.1) If transferId is the first transfer Id of this provider, then previousTransferId is zero and the latestSlashTransferId is INIT_SLASH_TRANSFER_ID - // 2.2) If transferId is not the first transfer, then it's latestSlashTransferId has the next two scenarios - // * the previousTransfer is a slash transfer, then latestSlashTransferId is previousTransferId - // * the previousTransfer is a normal relayed transfer, then latestSlashTransferId is previousTransfer's latestSlashTransferId - // I. transferId is trusted => previousTransferId is trusted => previousTransfer.previousTransferId is trusted => ... => firstTransfer is trusted - // II. transferId is trusted => previousTransferId is trusted => latestSlashTransferId is trusted if previousTransfer is a slash transfer - // III. Both I and II => latestSlashTransferId is trusted if previousTransfer is normal relayed tranfer - function _fillTransfer( - TransferParameter calldata params, - bytes32 expectedTransferId - ) internal { - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount)); - require(expectedTransferId == transferId, "check expected transferId failed"); - // Make sure this transfer was never filled before - require(fillTransfers[transferId] == bytes32(0), "fill exist"); - - _checkPreviousAndFillTransfer(transferId, params.previousTransferId); - - if (params.targetToken == address(0)) { - require(msg.value >= params.amount, "invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external { - // normal relay message, fill slasher as zero - require(params.provider == msg.sender, "invalid provider"); - _fillTransfer(params, expectedTransferId); - - emit TransferFilled(expectedTransferId, address(0)); - } - - // The condition for slash is that the transfer has timed out - // Meanwhile we need to request a slash transaction to the source chain to withdraw the LnProvider's margin - // On the source chain, we need to verify all the transfers before has been relayed or slashed. - // So we needs to carry the the previous shash transferId to ensure that the slash is continuous. - function _slashAndRemoteRefund( - TransferParameter calldata params, - bytes32 expectedTransferId - ) internal returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_REFUND_TIMESTAMP, "slash time not expired"); - _fillTransfer(params, expectedTransferId); - - // slasher = msg.sender - slashInfos[expectedTransferId] = SlashInfo(params.provider, params.sourceToken, msg.sender); - - // Do not slash `transferId` in source chain unless `latestSlashTransferId` has been slashed - message = _encodeSlashCall( - fillTransfers[expectedTransferId], - expectedTransferId, - params.provider, - params.sourceToken, - msg.sender - ); - emit TransferFilled(expectedTransferId, msg.sender); - } - - // we use this to verify that the transfer has been slashed by user and it can resend the slash request - function _retrySlashAndRemoteRefund(bytes32 transferId) internal view returns(bytes memory message) { - bytes32 latestSlashTransferId = fillTransfers[transferId]; - // transfer must be filled - require(latestSlashTransferId != bytes32(0), "invalid transfer id"); - // transfer must be slashed - SlashInfo memory slashInfo = slashInfos[transferId]; - require(slashInfo.slasher != address(0), "slasher not exist"); - message = _encodeSlashCall( - latestSlashTransferId, - transferId, - slashInfo.provider, - slashInfo.sourceToken, - slashInfo.slasher - ); - } - - function _encodeSlashCall( - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) internal pure returns(bytes memory) { - return abi.encodeWithSelector( - ILnOppositeBridgeSource.slash.selector, - latestSlashTransferId, - transferId, - provider, - sourceToken, - slasher - ); - } - - function _requestWithdrawMargin( - bytes32 lastTransferId, - address sourceToken, - uint112 amount - ) internal view returns(bytes memory message) { - bytes32 latestSlashTransferId = fillTransfers[lastTransferId]; - require(latestSlashTransferId != bytes32(0), "invalid last transfer"); - - return abi.encodeWithSelector( - ILnOppositeBridgeSource.withdrawMargin.selector, - latestSlashTransferId, - lastTransferId, - msg.sender, - sourceToken, - amount - ); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/Linea2EthTarget.sol -// License-Identifier: MIT - - - - -contract Linea2EthTarget is Initializable, LnAccessController, LnOppositeBridgeTarget { - ILineaMessageService public messageService; - address public remoteBridge; - - event WithdrawMargin(bytes32 lastTransferId, uint112 amount); - - receive() external payable {} - - function initialize(address _dao, address _messageService) public initializer { - messageService = ILineaMessageService(_messageService); - _initialize(_dao); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function _sendMessage( - bytes memory message, - uint256 fee - ) internal { - messageService.sendMessage{ value: fee }( - remoteBridge, - fee, - message - ); - } - - function slashAndRemoteRefund( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external whenNotPaused { - bytes memory refundCallMessage = _slashAndRemoteRefund( - params, - expectedTransferId - ); - uint256 valueUsed = address(0) == params.targetToken ? params.amount : 0; - _sendMessage(refundCallMessage, msg.value - valueUsed); - } - - function retryRemoteRefund( - bytes32 transferId - ) payable external whenNotPaused { - bytes memory refundCallMessage = _retrySlashAndRemoteRefund(transferId); - _sendMessage(refundCallMessage, msg.value); - } - - function requestWithdrawMargin( - bytes32 lastTransferId, - address sourceToken, - uint112 amount - ) payable external whenNotPaused { - bytes memory cancelWithdrawMarginCall = _requestWithdrawMargin( - lastTransferId, - sourceToken, - amount - ); - _sendMessage(cancelWithdrawMarginCall, msg.value); - emit WithdrawMargin(lastTransferId, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/LnBridgeBaseLZ.sol b/helix-contract/flatten/lnv2/LnBridgeBaseLZ.sol deleted file mode 100644 index 70a57e36..00000000 --- a/helix-contract/flatten/lnv2/LnBridgeBaseLZ.sol +++ /dev/null @@ -1,2388 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/25/2023 - **/ - -pragma solidity ^0.8.10; - -// 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 @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// File contracts/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnDefaultBridgeTarget.sol -// License-Identifier: MIT - -contract LnDefaultBridgeTarget is LnBridgeHelper { - uint256 constant private MIN_SLASH_TIMESTAMP = 30 * 60; - - struct ProviderInfo { - uint256 margin; - // use this slash gas reserve to pay the slash fee if transfer filled but timeout - uint256 slashReserveFund; - uint64 lastExpireFillTime; - uint64 withdrawNonce; - } - - // providerKey => margin - // providerKey = hash(provider, sourceToken, targetToken) - mapping(bytes32=>ProviderInfo) public lnProviderInfos; - - // if timestamp > 0, the Transfer has been relayed or slashed - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - struct FillTransfer { - uint64 timestamp; - address slasher; - } - - // transferId => FillTransfer - mapping(bytes32 => FillTransfer) public fillTransfers; - - event TransferFilled(address provider, bytes32 transferId); - event Slash(bytes32 transferId, address provider, address token, uint256 margin, address slasher); - event MarginUpdated(address provider, address token, uint256 amount, uint64 withdrawNonce); - event SlashReserveUpdated(address provider, address token, uint256 amount); - - function depositProviderMargin( - address sourceToken, - address targetToken, - uint256 margin - ) external payable { - require(margin > 0, "invalid margin"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin + margin; - lnProviderInfos[providerKey].margin = updatedMargin; - if (targetToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), margin); - } - emit MarginUpdated(msg.sender, sourceToken, updatedMargin, providerInfo.withdrawNonce); - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) external payable { - require(params.provider == msg.sender, "invalid provider"); - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - require(expectedTransferId == transferId, "check expected transferId failed"); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - // Make sure this transfer was never filled before - require(fillTransfer.timestamp == 0, "transfer has been filled"); - - fillTransfers[transferId].timestamp = uint64(block.timestamp); - if (block.timestamp - MIN_SLASH_TIMESTAMP > params.timestamp) { - bytes32 providerKey = getDefaultProviderKey(msg.sender, params.sourceToken, params.targetToken); - lnProviderInfos[providerKey].lastExpireFillTime = uint64(block.timestamp); - } - - if (params.targetToken == address(0)) { - require(msg.value == params.amount, "lnBridgeTarget:invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - emit TransferFilled(params.provider, transferId); - } - - function depositSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external payable { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedAmount = providerInfo.slashReserveFund + amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - require(msg.value == amount, "amount invalid"); - } else { - _safeTransferFrom(targetToken, msg.sender, address(this), amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - // withdraw slash fund - // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time - function withdrawSlashFundReserve( - address sourceToken, - address targetToken, - uint256 amount - ) external { - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - require(amount <= providerInfo.slashReserveFund, "reserve not enough"); - require(block.timestamp - MIN_SLASH_TIMESTAMP >= providerInfo.lastExpireFillTime, "time not expired"); - uint256 updatedAmount = providerInfo.slashReserveFund - amount; - lnProviderInfos[providerKey].slashReserveFund = updatedAmount; - if (targetToken == address(0)) { - _safeTransferNative(msg.sender, amount); - } else { - _safeTransfer(targetToken, msg.sender, amount); - } - emit SlashReserveUpdated(msg.sender, sourceToken, updatedAmount); - } - - function _withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) internal { - // ensure all transfer has finished - require(lastTransferId == bytes32(0) || fillTransfers[lastTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - // all the early withdraw info ignored - require(providerInfo.withdrawNonce < withdrawNonce, "withdraw nonce expired"); - - // transfer token - require(providerInfo.margin >= amount, "margin not enough"); - uint256 updatedMargin = providerInfo.margin - amount; - lnProviderInfos[providerKey].margin = updatedMargin; - lnProviderInfos[providerKey].withdrawNonce = withdrawNonce; - - if (targetToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(targetToken, provider, amount); - } - emit MarginUpdated(provider, sourceToken, updatedMargin, withdrawNonce); - } - - function _slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) internal { - require(params.previousTransferId == bytes32(0) || fillTransfers[params.previousTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount - )); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - require(fillTransfer.slasher == address(0), "transfer has been slashed"); - bytes32 providerKey = getDefaultProviderKey(params.provider, params.sourceToken, params.targetToken); - ProviderInfo memory providerInfo = lnProviderInfos[providerKey]; - uint256 updatedMargin = providerInfo.margin; - // transfer is not filled - if (fillTransfer.timestamp == 0) { - require(params.timestamp < block.timestamp - MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), slasher); - - // 1. transfer token to receiver - // 2. trnasfer fee and penalty to slasher - // update margin - uint256 marginCost = params.amount + fee + penalty; - require(providerInfo.margin >= marginCost, "margin not enough"); - updatedMargin = providerInfo.margin - marginCost; - lnProviderInfos[providerKey].margin = updatedMargin; - - if (params.targetToken == address(0)) { - _safeTransferNative(params.receiver, params.amount); - _safeTransferNative(slasher, fee + penalty); - } else { - _safeTransfer(params.targetToken, params.receiver, uint256(params.amount)); - _safeTransfer(params.targetToken, slasher, fee + penalty); - } - } else { - require(fillTransfer.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "time not expired"); - fillTransfers[transferId].slasher = slasher; - uint112 slashRefund = penalty / 5; - // transfer slashRefund to slasher - require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); - lnProviderInfos[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; - if (params.targetToken == address(0)) { - _safeTransferNative(slasher, slashRefund); - } else { - _safeTransfer(params.targetToken, slasher, slashRefund); - } - } - emit Slash(transferId, params.provider, params.sourceToken, updatedMargin, slasher); - } -} - -// File contracts/ln/interface/ILnDefaultBridgeTarget.sol -// License-Identifier: MIT - - -interface ILnDefaultBridgeTarget { - function slash( - LnBridgeHelper.TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external; - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external; -} - -// File contracts/ln/base/LnDefaultBridgeSource.sol -// License-Identifier: MIT - - - -/// @title LnPositiveBridgeSource -/// @notice LnPositiveBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can send a slash request message to target chain, then force transfer from lnProvider's margin to the user. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnDefaultBridgeSource is LnBridgeHelper { - // the time(seconds) for liquidity provider to delivery message - // if timeout, slasher can work. - uint256 constant private MIN_SLASH_TIMESTAMP = 30 * 60; - // liquidity fee base rate - // liquidityFee = liquidityFeeRate / LIQUIDITY_FEE_RATE_BASE * sendAmount - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - // max transfer amount one time - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - - // provider fee is paid to liquidity node's account - // the fee is charged by the same token that user transfered - // providerFee = baseFee + liquidityFeeRate/LIQUIDITY_FEE_RATE_BASE * sendAmount - struct LnProviderFee { - uint112 baseFee; - uint8 liquidityFeeRate; - } - - struct LnProviderInfo { - LnProviderFee fee; - // we use this nonce to generate the unique withdraw id - uint64 withdrawNonce; - bytes32 lastTransferId; - } - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId or withdrawNonce updated, revert - // 2. if totalFee increase, revert - // 3. if totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 totalFee; - uint64 withdrawNonce; - } - - // lock info - // the fee and penalty is the state of the transfer confirmed - struct LockInfo { - uint112 fee; - uint112 penalty; - bool isLocked; - } - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // providerKey => provider info - mapping(bytes32=>LnProviderInfo) public lnProviders; - // transferId => lock info - mapping(bytes32=>LockInfo) public lockInfos; - - address public protocolFeeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LnProviderUpdated(address provider, address sourceToken, uint112 baseFee, uint8 liquidityfeeRate); - - // protocolFeeReceiver is the protocol fee reciever, we don't use the contract itself as the receiver - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - protocolFeeReceiver = _feeReceiver; - } - - // register or update token info, it can be only called by contract owner - // source token can only map a unique target token on target chain - function _setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) internal { - tokenInfos[_sourceToken] = TokenInfo( - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals, - true - ); - } - - // lnProvider register - // 1. set fee on source chain - // 2. deposit margin on target chain - function setProviderFee( - address sourceToken, - uint112 baseFee, - uint8 liquidityFeeRate - ) external { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderFee memory providerFee = LnProviderFee(baseFee, liquidityFeeRate); - - // we only update the field fee of the provider info - // if the provider has not been registered, then this line will register, otherwise update fee - lnProviders[providerKey].fee = providerFee; - - emit LnProviderUpdated(msg.sender, sourceToken, baseFee, liquidityFeeRate); - } - - function calculateProviderFee(LnProviderFee memory fee, uint112 amount) internal pure returns(uint256) { - return uint256(fee.baseFee) + uint256(fee.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - bytes32 providerKey = getDefaultProviderKey(provider, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - return providerFee + tokenInfo.protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, withdrawNonce) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(snapshot.provider, snapshot.sourceToken, tokenInfo.targetToken); - - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.fee, amount); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired:transfer"); - require(snapshot.withdrawNonce == providerInfo.withdrawNonce, "snapshot expired:withdraw"); - require(snapshot.totalFee >= providerFee + tokenInfo.protocolFee && providerFee > 0, "fee is invalid"); - - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(amount)); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - targetAmount - )); - require(!lockInfos[transferId].isLocked, "transferId exist"); - // if the transfer refund, then the fee and penalty should be given to slasher, but the protocol fee is ignored - // and we use the penalty value configure at the moment transfer confirmed - lockInfos[transferId] = LockInfo(snapshot.totalFee, tokenInfo.penaltyLnCollateral, true); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(protocolFeeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - protocolFeeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - targetAmount, - uint112(providerFee), - timestamp, - receiver); - } - - function _sourceAmountToTargetAmount( - TokenInfo memory tokenInfo, - uint256 amount - ) internal pure returns(uint112) { - uint256 targetAmount = amount * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - return uint112(targetAmount); - } - - function _slashAndRemoteRelease( - TransferParameter memory params, - bytes32 expectedTransferId - ) internal view returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_SLASH_TIMESTAMP, "invalid timestamp"); - TokenInfo memory tokenInfo = tokenInfos[params.sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, uint256(params.amount)); - - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - targetAmount - )); - require(expectedTransferId == transferId, "expected transfer id not match"); - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.isLocked, "lock info not match"); - uint112 targetFee = _sourceAmountToTargetAmount(tokenInfo, lockInfo.fee); - uint112 targetPenalty = _sourceAmountToTargetAmount(tokenInfo, lockInfo.penalty); - - message = _encodeSlashCall( - params, - msg.sender, - targetFee, - targetPenalty - ); - } - - function _withdrawMargin( - address sourceToken, - uint112 amount - ) internal returns(bytes memory message) { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token not registered"); - - bytes32 providerKey = getDefaultProviderKey(msg.sender, sourceToken, tokenInfo.targetToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - lnProviders[providerKey].withdrawNonce = providerInfo.withdrawNonce + 1; - uint112 targetAmount = _sourceAmountToTargetAmount(tokenInfo, amount); - message = _encodeWithdrawCall( - providerInfo.lastTransferId, - providerInfo.withdrawNonce + 1, - msg.sender, - sourceToken, - tokenInfo.targetToken, - targetAmount - ); - } - - function _encodeSlashCall( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) public pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.slash.selector, - params, - slasher, - fee, - penalty - ); - } - - function _encodeWithdrawCall( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) public pure returns(bytes memory message) { - return abi.encodeWithSelector( - ILnDefaultBridgeTarget.withdraw.selector, - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - } -} - -// File contracts/ln/interface/ILayerZeroEndpoint.sol -// License-Identifier: MIT - -interface ILayerZeroEndpoint { - function send( - uint16 _dstChainId, - bytes calldata _destination, - bytes calldata _payload, - address payable _refundAddress, - address _zroPaymentAddress, - bytes calldata _adapterParams - ) external payable; - - function estimateFees( - uint16 _dstChainId, - address _userApplication, - bytes calldata _payload, - bool _payInZRO, - bytes calldata _adapterParam - ) external view returns (uint nativeFee, uint zroFee); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/LnBridgeBaseLZ.sol -// License-Identifier: MIT - - - - - -contract LnBridgeBaseLZ is Initializable, LnAccessController, LnDefaultBridgeSource, LnDefaultBridgeTarget { - ILayerZeroEndpoint public endpoint; - address public remoteBridge; - bytes32 public trustedRemote; - uint16 public remoteChainId; - - event WithdrawMargin(address sourceToken, uint112 amount); - event CallResult(bytes srcAddress, bool successed); - - receive() external payable {} - - modifier onlyRemoteBridge(bytes calldata srcAddress) { - require(msg.sender == address(endpoint), "invalid caller"); - require(trustedRemote == keccak256(srcAddress), "invalid remote caller"); - _; - } - - function initialize(address _dao, address _endpoint, uint16 _remoteChainId) public initializer { - _initialize(_dao); - endpoint = ILayerZeroEndpoint(_endpoint); - _setFeeReceiver(_dao); - remoteChainId = _remoteChainId; - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - trustedRemote = keccak256(abi.encodePacked(_remoteBridge, address(this))); - } - - function setTokenInfo( - address _sourceToken, - address _targetToken, - uint112 _protocolFee, - uint112 _penaltyLnCollateral, - uint8 _sourceDecimals, - uint8 _targetDecimals - ) external onlyDao { - _setTokenInfo( - _sourceToken, - _targetToken, - _protocolFee, - _penaltyLnCollateral, - _sourceDecimals, - _targetDecimals - ); - } - - function estimateSlashFee( - TransferParameter calldata params - ) external view returns(uint256 nativeFee, uint256 zroFee) { - bytes memory slashCallMessage = _encodeSlashCall( - params, - msg.sender, - 0, - 0 - ); - return endpoint.estimateFees( - remoteChainId, - remoteBridge, - slashCallMessage, - false, - bytes("") - ); - } - - function estimateWithdrawFee( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external view returns(uint256 nativeFee, uint256 zroFee) { - bytes memory withdrawCallMessage = _encodeWithdrawCall( - lastTransferId, - withdrawNonce, - provider, - sourceToken, - targetToken, - amount - ); - return endpoint.estimateFees( - remoteChainId, - remoteBridge, - withdrawCallMessage, - false, - bytes("") - ); - } - - function _sendMessage( - bytes memory message, - uint256 prepaid - ) internal { - bytes memory destination = abi.encodePacked( - remoteBridge, - address(this) - ); - endpoint.send{ value: prepaid }( - remoteChainId, - destination, - message, - payable(msg.sender), - // zro payment, future parameter - address(0x0), - bytes("") - ); - } - - function slashAndRemoteRelease( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external whenNotPaused { - bytes memory slashCallMessage = _slashAndRemoteRelease( - params, - expectedTransferId - ); - _sendMessage(slashCallMessage, msg.value); - } - - function requestWithdrawMargin( - address sourceToken, - uint112 amount - ) payable external whenNotPaused { - bytes memory withdrawCallMessage = _withdrawMargin( - sourceToken, - amount - ); - _sendMessage(withdrawCallMessage, msg.value); - emit WithdrawMargin(sourceToken, amount); - } - - function lzReceive( - uint16 _srcChainId, - bytes calldata _srcAddress, - uint64, //nonce unused - bytes calldata _payload) onlyRemoteBridge(_srcAddress) whenNotPaused external { - require(_srcChainId == remoteChainId, "invalid src chainid"); - // call - (bool success,) = address(this).call(_payload); - // don't revert to prevent message block - emit CallResult(_srcAddress, success); - } - - function slash( - TransferParameter memory params, - address slasher, - uint112 fee, - uint112 penalty - ) external { - require(msg.sender == address(this), "only self"); - _slash( - params, - slasher, - fee, - penalty - ); - } - - function withdraw( - bytes32 lastTransferId, - uint64 withdrawNonce, - address provider, - address sourceToken, - address targetToken, - uint112 amount - ) external { - require(msg.sender == address(this), "only self"); - _withdraw(lastTransferId, withdrawNonce, provider, sourceToken, targetToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/LnDefaultBridge.sol b/helix-contract/flatten/lnv2/LnDefaultBridge.sol index ef0e4624..a54959f4 100644 --- a/helix-contract/flatten/lnv2/LnDefaultBridge.sol +++ b/helix-contract/flatten/lnv2/LnDefaultBridge.sol @@ -14,10 +14,23 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; +pragma solidity ^0.8.17; + +// File contracts/ln/interface/ILowLevelMessager.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/ln/base/LnAccessController.sol // License-Identifier: MIT @@ -55,7 +68,7 @@ contract LnAccessController { operator = _operator; } - function authoriseAppCaller(address appAddress, bool enable) onlyOperator external { + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { callerWhiteList[appAddress] = enable; } @@ -64,19 +77,6 @@ contract LnAccessController { } } -// File contracts/ln/interface/ILowLevelMessager.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 @zeppelin-solidity/contracts/token/ERC20/IERC20.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) @@ -264,237 +264,9 @@ library LnBridgeHelper { } } -// File contracts/ln/base/LnDefaultBridgeTarget.sol -// License-Identifier: MIT - -contract LnDefaultBridgeTarget { - struct TargetProviderInfo { - uint256 margin; - // use this slash gas reserve to pay the slash fee if transfer filled but timeout - uint256 slashReserveFund; - uint64 lastExpireFillTime; - uint64 withdrawNonce; - } - - // providerKey => margin - // providerKey = hash(remoteChainId, provider, sourceToken, targetToken) - mapping(bytes32=>TargetProviderInfo) public tgtProviders; - - // if timestamp > 0, the Transfer has been relayed or slashed - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - struct FillTransfer { - uint64 timestamp; - address slasher; - } - - // transferId => FillTransfer - mapping(bytes32 => FillTransfer) public fillTransfers; - - event TransferFilled(bytes32 transferId, address provider); - event Slash(bytes32 transferId, uint256 remoteChainId, address provider, address sourceToken, address targetToken, uint256 margin, address slasher); - event MarginUpdated(uint256 remoteChainId, address provider, address sourceToken, address targetToken, uint256 amount, uint64 withdrawNonce); - event SlashReserveUpdated(address provider, address sourceToken, address targetToken, uint256 amount); - - modifier allowRemoteCall(uint256 _remoteChainId) { - _verifyRemote(_remoteChainId); - _; - } - - function _verifyRemote(uint256 _remoteChainId) internal virtual {} - - function depositProviderMargin( - uint256 _remoteChainId, - address _sourceToken, - address _targetToken, - uint256 _margin - ) external payable { - require(_margin > 0, "invalid margin"); - bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _sourceToken, _targetToken); - TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; - uint256 updatedMargin = providerInfo.margin + _margin; - tgtProviders[providerKey].margin = updatedMargin; - if (_targetToken == address(0)) { - require(msg.value == _margin, "invalid margin value"); - } else { - LnBridgeHelper.safeTransferFrom(_targetToken, msg.sender, address(this), _margin); - } - emit MarginUpdated(_remoteChainId, msg.sender, _sourceToken, _targetToken, updatedMargin, providerInfo.withdrawNonce); - } - - function transferAndReleaseMargin( - LnBridgeHelper.TransferParameter calldata _params, - uint256 _remoteChainId, - bytes32 _expectedTransferId - ) external payable { - require(_params.provider == msg.sender, "invalid provider"); - require(_params.previousTransferId == bytes32(0) || fillTransfers[_params.previousTransferId].timestamp > 0, "last transfer not filled"); - bytes32 transferId = keccak256(abi.encodePacked( - _remoteChainId, - block.chainid, - _params.previousTransferId, - _params.provider, - _params.sourceToken, - _params.targetToken, - _params.receiver, - _params.amount - )); - require(_expectedTransferId == transferId, "check expected transferId failed"); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - // Make sure this transfer was never filled before - require(fillTransfer.timestamp == 0, "transfer has been filled"); - - fillTransfers[transferId].timestamp = uint64(block.timestamp); - if (block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME > _params.timestamp) { - bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _params.sourceToken, _params.targetToken); - tgtProviders[providerKey].lastExpireFillTime = uint64(block.timestamp); - } - - if (_params.targetToken == address(0)) { - require(msg.value == _params.amount, "lnBridgeTarget:invalid amount"); - LnBridgeHelper.safeTransferNative(_params.receiver, _params.amount); - } else { - LnBridgeHelper.safeTransferFrom(_params.targetToken, msg.sender, _params.receiver, uint256(_params.amount)); - } - emit TransferFilled(transferId, _params.provider); - } - - function depositSlashFundReserve( - uint256 _remoteChainId, - address _sourceToken, - address _targetToken, - uint256 _amount - ) external payable { - bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _sourceToken, _targetToken); - TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; - uint256 updatedAmount = providerInfo.slashReserveFund + _amount; - tgtProviders[providerKey].slashReserveFund = updatedAmount; - if (_targetToken == address(0)) { - require(msg.value == _amount, "amount invalid"); - } else { - LnBridgeHelper.safeTransferFrom(_targetToken, msg.sender, address(this), _amount); - } - emit SlashReserveUpdated(msg.sender, _sourceToken, _targetToken, updatedAmount); - } - - // withdraw slash fund - // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time - function withdrawSlashFundReserve( - uint256 _remoteChainId, - address _sourceToken, - address _targetToken, - uint256 _amount - ) external { - bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _sourceToken, _targetToken); - TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; - require(_amount <= providerInfo.slashReserveFund, "reserve not enough"); - require(block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME >= providerInfo.lastExpireFillTime, "time not expired"); - uint256 updatedAmount = providerInfo.slashReserveFund - _amount; - tgtProviders[providerKey].slashReserveFund = updatedAmount; - if (_targetToken == address(0)) { - LnBridgeHelper.safeTransferNative(msg.sender, _amount); - } else { - LnBridgeHelper.safeTransfer(_targetToken, msg.sender, _amount); - } - emit SlashReserveUpdated(msg.sender, _sourceToken, _targetToken, updatedAmount); - } - - function withdraw( - uint256 _remoteChainId, - bytes32 _lastTransferId, - uint64 _withdrawNonce, - address _provider, - address _sourceToken, - address _targetToken, - uint112 _amount - ) external allowRemoteCall(_remoteChainId) { - // ensure all transfer has finished - require(_lastTransferId == bytes32(0) || fillTransfers[_lastTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, _provider, _sourceToken, _targetToken); - TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; - // all the early withdraw info ignored - require(providerInfo.withdrawNonce < _withdrawNonce, "withdraw nonce expired"); - - // transfer token - require(providerInfo.margin >= _amount, "margin not enough"); - uint256 updatedMargin = providerInfo.margin - _amount; - tgtProviders[providerKey].margin = updatedMargin; - tgtProviders[providerKey].withdrawNonce = _withdrawNonce; - - if (_targetToken == address(0)) { - LnBridgeHelper.safeTransferNative(_provider, _amount); - } else { - LnBridgeHelper.safeTransfer(_targetToken, _provider, _amount); - } - emit MarginUpdated(_remoteChainId, _provider, _sourceToken, _targetToken, updatedMargin, _withdrawNonce); - } - - function slash( - LnBridgeHelper.TransferParameter memory _params, - uint256 _remoteChainId, - address _slasher, - uint112 _fee, - uint112 _penalty - ) external allowRemoteCall(_remoteChainId) { - require(_params.previousTransferId == bytes32(0) || fillTransfers[_params.previousTransferId].timestamp > 0, "last transfer not filled"); - - bytes32 transferId = keccak256(abi.encodePacked( - _remoteChainId, - block.chainid, - _params.previousTransferId, - _params.provider, - _params.sourceToken, - _params.targetToken, - _params.receiver, - _params.amount - )); - FillTransfer memory fillTransfer = fillTransfers[transferId]; - require(fillTransfer.slasher == address(0), "transfer has been slashed"); - bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, _params.provider, _params.sourceToken, _params.targetToken); - TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; - uint256 updatedMargin = providerInfo.margin; - // transfer is not filled - if (fillTransfer.timestamp == 0) { - require(_params.timestamp < block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME, "time not expired"); - fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), _slasher); - - // 1. transfer token to receiver - // 2. trnasfer fee and penalty to slasher - // update margin - uint256 marginCost = _params.amount + _fee + _penalty; - require(providerInfo.margin >= marginCost, "margin not enough"); - updatedMargin = providerInfo.margin - marginCost; - tgtProviders[providerKey].margin = updatedMargin; - - if (_params.targetToken == address(0)) { - LnBridgeHelper.safeTransferNative(_params.receiver, _params.amount); - LnBridgeHelper.safeTransferNative(_slasher, _fee + _penalty); - } else { - LnBridgeHelper.safeTransfer(_params.targetToken, _params.receiver, uint256(_params.amount)); - LnBridgeHelper.safeTransfer(_params.targetToken, _slasher, _fee + _penalty); - } - } else { - require(fillTransfer.timestamp > _params.timestamp + LnBridgeHelper.SLASH_EXPIRE_TIME, "time not expired"); - fillTransfers[transferId].slasher = _slasher; - uint112 slashRefund = _penalty / 5; - // transfer slashRefund to slasher - require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); - tgtProviders[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; - if (_params.targetToken == address(0)) { - LnBridgeHelper.safeTransferNative(_slasher, slashRefund); - } else { - LnBridgeHelper.safeTransfer(_params.targetToken, _slasher, slashRefund); - } - } - emit Slash(transferId, _remoteChainId, _params.provider, _params.sourceToken, _params.targetToken, updatedMargin, _slasher); - } -} - // File contracts/ln/interface/ILnDefaultBridgeTarget.sol // License-Identifier: MIT - interface ILnDefaultBridgeTarget { function slash( LnBridgeHelper.TransferParameter memory params, @@ -1023,6 +795,233 @@ contract LnDefaultBridgeSource is Pausable { } } +// File contracts/ln/base/LnDefaultBridgeTarget.sol +// License-Identifier: MIT + +contract LnDefaultBridgeTarget { + struct TargetProviderInfo { + uint256 margin; + // use this slash gas reserve to pay the slash fee if transfer filled but timeout + uint256 slashReserveFund; + uint64 lastExpireFillTime; + uint64 withdrawNonce; + } + + // providerKey => margin + // providerKey = hash(remoteChainId, provider, sourceToken, targetToken) + mapping(bytes32=>TargetProviderInfo) public tgtProviders; + + // if timestamp > 0, the Transfer has been relayed or slashed + // if slasher == address(0), this FillTransfer is relayed by lnProvider + // otherwise, this FillTransfer is slashed by slasher + struct FillTransfer { + uint64 timestamp; + address slasher; + } + + // transferId => FillTransfer + mapping(bytes32 => FillTransfer) public fillTransfers; + + event TransferFilled(bytes32 transferId, address provider); + event Slash(bytes32 transferId, uint256 remoteChainId, address provider, address sourceToken, address targetToken, uint256 margin, address slasher); + event MarginUpdated(uint256 remoteChainId, address provider, address sourceToken, address targetToken, uint256 amount, uint64 withdrawNonce); + event SlashReserveUpdated(address provider, address sourceToken, address targetToken, uint256 amount); + + modifier allowRemoteCall(uint256 _remoteChainId) { + _verifyRemote(_remoteChainId); + _; + } + + function _verifyRemote(uint256 _remoteChainId) internal virtual {} + + function depositProviderMargin( + uint256 _remoteChainId, + address _sourceToken, + address _targetToken, + uint256 _margin + ) external payable { + require(_margin > 0, "invalid margin"); + bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _sourceToken, _targetToken); + TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; + uint256 updatedMargin = providerInfo.margin + _margin; + tgtProviders[providerKey].margin = updatedMargin; + if (_targetToken == address(0)) { + require(msg.value == _margin, "invalid margin value"); + } else { + LnBridgeHelper.safeTransferFrom(_targetToken, msg.sender, address(this), _margin); + } + emit MarginUpdated(_remoteChainId, msg.sender, _sourceToken, _targetToken, updatedMargin, providerInfo.withdrawNonce); + } + + function transferAndReleaseMargin( + LnBridgeHelper.TransferParameter calldata _params, + uint256 _remoteChainId, + bytes32 _expectedTransferId + ) external payable { + require(_params.provider == msg.sender, "invalid provider"); + require(_params.previousTransferId == bytes32(0) || fillTransfers[_params.previousTransferId].timestamp > 0, "last transfer not filled"); + bytes32 transferId = keccak256(abi.encodePacked( + _remoteChainId, + block.chainid, + _params.previousTransferId, + _params.provider, + _params.sourceToken, + _params.targetToken, + _params.receiver, + _params.amount + )); + require(_expectedTransferId == transferId, "check expected transferId failed"); + FillTransfer memory fillTransfer = fillTransfers[transferId]; + // Make sure this transfer was never filled before + require(fillTransfer.timestamp == 0, "transfer has been filled"); + + fillTransfers[transferId].timestamp = uint64(block.timestamp); + if (block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME > _params.timestamp) { + bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _params.sourceToken, _params.targetToken); + tgtProviders[providerKey].lastExpireFillTime = uint64(block.timestamp); + } + + if (_params.targetToken == address(0)) { + require(msg.value == _params.amount, "lnBridgeTarget:invalid amount"); + LnBridgeHelper.safeTransferNative(_params.receiver, _params.amount); + } else { + LnBridgeHelper.safeTransferFrom(_params.targetToken, msg.sender, _params.receiver, uint256(_params.amount)); + } + emit TransferFilled(transferId, _params.provider); + } + + function depositSlashFundReserve( + uint256 _remoteChainId, + address _sourceToken, + address _targetToken, + uint256 _amount + ) external payable { + bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _sourceToken, _targetToken); + TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; + uint256 updatedAmount = providerInfo.slashReserveFund + _amount; + tgtProviders[providerKey].slashReserveFund = updatedAmount; + if (_targetToken == address(0)) { + require(msg.value == _amount, "amount invalid"); + } else { + LnBridgeHelper.safeTransferFrom(_targetToken, msg.sender, address(this), _amount); + } + emit SlashReserveUpdated(msg.sender, _sourceToken, _targetToken, updatedAmount); + } + + // withdraw slash fund + // provider can't withdraw until the block.timestamp overtime lastExpireFillTime for a period of time + function withdrawSlashFundReserve( + uint256 _remoteChainId, + address _sourceToken, + address _targetToken, + uint256 _amount + ) external { + bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _sourceToken, _targetToken); + TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; + require(_amount <= providerInfo.slashReserveFund, "reserve not enough"); + require(block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME >= providerInfo.lastExpireFillTime, "time not expired"); + uint256 updatedAmount = providerInfo.slashReserveFund - _amount; + tgtProviders[providerKey].slashReserveFund = updatedAmount; + if (_targetToken == address(0)) { + LnBridgeHelper.safeTransferNative(msg.sender, _amount); + } else { + LnBridgeHelper.safeTransfer(_targetToken, msg.sender, _amount); + } + emit SlashReserveUpdated(msg.sender, _sourceToken, _targetToken, updatedAmount); + } + + function withdraw( + uint256 _remoteChainId, + bytes32 _lastTransferId, + uint64 _withdrawNonce, + address _provider, + address _sourceToken, + address _targetToken, + uint112 _amount + ) external allowRemoteCall(_remoteChainId) { + // ensure all transfer has finished + require(_lastTransferId == bytes32(0) || fillTransfers[_lastTransferId].timestamp > 0, "last transfer not filled"); + + bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, _provider, _sourceToken, _targetToken); + TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; + // all the early withdraw info ignored + require(providerInfo.withdrawNonce < _withdrawNonce, "withdraw nonce expired"); + + // transfer token + require(providerInfo.margin >= _amount, "margin not enough"); + uint256 updatedMargin = providerInfo.margin - _amount; + tgtProviders[providerKey].margin = updatedMargin; + tgtProviders[providerKey].withdrawNonce = _withdrawNonce; + + if (_targetToken == address(0)) { + LnBridgeHelper.safeTransferNative(_provider, _amount); + } else { + LnBridgeHelper.safeTransfer(_targetToken, _provider, _amount); + } + emit MarginUpdated(_remoteChainId, _provider, _sourceToken, _targetToken, updatedMargin, _withdrawNonce); + } + + function slash( + LnBridgeHelper.TransferParameter memory _params, + uint256 _remoteChainId, + address _slasher, + uint112 _fee, + uint112 _penalty + ) external allowRemoteCall(_remoteChainId) { + require(_params.previousTransferId == bytes32(0) || fillTransfers[_params.previousTransferId].timestamp > 0, "last transfer not filled"); + + bytes32 transferId = keccak256(abi.encodePacked( + _remoteChainId, + block.chainid, + _params.previousTransferId, + _params.provider, + _params.sourceToken, + _params.targetToken, + _params.receiver, + _params.amount + )); + FillTransfer memory fillTransfer = fillTransfers[transferId]; + require(fillTransfer.slasher == address(0), "transfer has been slashed"); + bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, _params.provider, _params.sourceToken, _params.targetToken); + TargetProviderInfo memory providerInfo = tgtProviders[providerKey]; + uint256 updatedMargin = providerInfo.margin; + // transfer is not filled + if (fillTransfer.timestamp == 0) { + require(_params.timestamp < block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME, "time not expired"); + fillTransfers[transferId] = FillTransfer(uint64(block.timestamp), _slasher); + + // 1. transfer token to receiver + // 2. trnasfer fee and penalty to slasher + // update margin + uint256 marginCost = _params.amount + _fee + _penalty; + require(providerInfo.margin >= marginCost, "margin not enough"); + updatedMargin = providerInfo.margin - marginCost; + tgtProviders[providerKey].margin = updatedMargin; + + if (_params.targetToken == address(0)) { + LnBridgeHelper.safeTransferNative(_params.receiver, _params.amount); + LnBridgeHelper.safeTransferNative(_slasher, _fee + _penalty); + } else { + LnBridgeHelper.safeTransfer(_params.targetToken, _params.receiver, uint256(_params.amount)); + LnBridgeHelper.safeTransfer(_params.targetToken, _slasher, _fee + _penalty); + } + } else { + require(fillTransfer.timestamp > _params.timestamp + LnBridgeHelper.SLASH_EXPIRE_TIME, "time not expired"); + fillTransfers[transferId].slasher = _slasher; + uint112 slashRefund = _penalty / 5; + // transfer slashRefund to slasher + require(providerInfo.slashReserveFund >= slashRefund, "slashReserveFund not enough"); + tgtProviders[providerKey].slashReserveFund = providerInfo.slashReserveFund - slashRefund; + if (_params.targetToken == address(0)) { + LnBridgeHelper.safeTransferNative(_slasher, slashRefund); + } else { + LnBridgeHelper.safeTransfer(_params.targetToken, _slasher, slashRefund); + } + } + emit Slash(transferId, _remoteChainId, _params.provider, _params.sourceToken, _params.targetToken, updatedMargin, _slasher); + } +} + // File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) diff --git a/helix-contract/flatten/lnv2/LnOppositeBridge.sol b/helix-contract/flatten/lnv2/LnOppositeBridge.sol index 469d7dc4..547d3f49 100644 --- a/helix-contract/flatten/lnv2/LnOppositeBridge.sol +++ b/helix-contract/flatten/lnv2/LnOppositeBridge.sol @@ -14,10 +14,10 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; +pragma solidity ^0.8.17; // File contracts/ln/base/LnAccessController.sol // License-Identifier: MIT @@ -55,7 +55,7 @@ contract LnAccessController { operator = _operator; } - function authoriseAppCaller(address appAddress, bool enable) onlyOperator external { + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { callerWhiteList[appAddress] = enable; } @@ -733,7 +733,6 @@ contract LnOppositeBridgeSource is Pausable { // File contracts/ln/interface/ILnOppositeBridgeSource.sol // License-Identifier: MIT - interface ILnOppositeBridgeSource { function slash( bytes32 lastRefundTransferId, diff --git a/helix-contract/flatten/lnv2/TestToken.sol b/helix-contract/flatten/lnv2/TestToken.sol index 11d12b2c..15fcc996 100644 --- a/helix-contract/flatten/lnv2/TestToken.sol +++ b/helix-contract/flatten/lnv2/TestToken.sol @@ -14,93 +14,10 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; - -// 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); -} +pragma solidity ^0.8.17; // File @zeppelin-solidity/contracts/utils/math/SafeMath.sol@v4.7.3 // License-Identifier: MIT @@ -437,6 +354,89 @@ abstract contract Ownable 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 contracts/ln/test/TestToken.sol // License-Identifier: MIT diff --git a/helix-contract/flatten/lnv2/ZkSync2EthSource.sol b/helix-contract/flatten/lnv2/ZkSync2EthSource.sol deleted file mode 100644 index 6f831dfa..00000000 --- a/helix-contract/flatten/lnv2/ZkSync2EthSource.sol +++ /dev/null @@ -1,2025 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/11/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnOppositeBridgeSource.sol -// License-Identifier: MIT - - -/// @title LnBridgeSource -/// @notice LnBridgeSource is a contract to help user transfer token to liquidity node and generate proof, -/// then the liquidity node must transfer the same amount of the token to the user on target chain. -/// Otherwise if timeout the slasher can paid for relayer and slash the transfer, then request slash from lnProvider's margin. -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnOppositeBridgeSource is LnBridgeHelper { - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000; - - // the registered token info - // sourceToken and targetToken is the pair of erc20 token addresses - // if sourceToken == address(0), then it's native token - // if targetToken == address(0), then remote is native token - // * `protocolFee` is the protocol fee charged by system - // * `penaltyLnCollateral` is penalty from lnProvider when the transfer slashed, if we adjust this value, it'll not affect the old transfers. - struct TokenInfo { - address targetToken; - uint112 protocolFee; - uint112 penaltyLnCollateral; - uint8 sourceDecimals; - uint8 targetDecimals; - bool isRegistered; - } - // the Liquidity Node provider info - // Liquidity Node need register first - struct LnProviderConfigure { - uint112 margin; - uint112 baseFee; - // liquidityFeeRate / 100,000 * amount = liquidityFee - // the max liquidity fee rate is 0.255% - uint8 liquidityFeeRate; - } - struct LnProviderInfo { - LnProviderConfigure config; - bool pause; - bytes32 lastTransferId; - } - - // the Snapshot is the state of the token bridge when user prepare to transfer across chains. - // If the snapshot updated when the across chain transfer confirmed, it will - // 1. if lastTransferId updated, revert - // 2. if margin decrease or totalFee increase, revert - // 3. if margin increase or totalFee decrease, success - struct Snapshot { - address provider; - address sourceToken; - bytes32 transferId; - uint112 depositedMargin; - uint112 totalFee; - } - // registered token info - // sourceToken => token info - mapping(address=>TokenInfo) public tokenInfos; - // registered lnProviders - mapping(bytes32=>LnProviderInfo) public lnProviders; - // each time cross chain transfer, amount and fee can't be larger than type(uint112).max - struct LockInfo { - // amount + providerFee + penaltyLnCollateral - // the Indexer should be care about this value, it will frozen lnProvider's margin when the transfer not finished. - // and when the slasher slash success, this amount of token will be transfer from lnProvider's margin to slasher. - uint112 amountWithFeeAndPenalty; - bool hasSlashed; - } - // key: transferId = hash(proviousTransferId, timestamp, targetToken, receiver, targetAmount) - // * `proviousTransferId` is used to ensure the continuous of the transfer - // * `timestamp` is the block.timestmap to judge timeout on target chain(here we support source and target chain has the same world clock) - // * `targetToken`, `receiver` and `targetAmount` are used on target chain to transfer target token. - mapping(bytes32 => LockInfo) public lockInfos; - address public feeReceiver; - - event TokenLocked( - bytes32 transferId, - address provider, - address sourceToken, - uint112 amount, - uint112 fee, - uint64 timestamp, - address receiver); - event LiquidityWithdrawn(address provider, address token, uint112 amount); - event Slash(bytes32 transferId, address provider, address token, uint112 margin, address slasher); - // relayer - event LnProviderUpdated(address provider, address token, uint112 margin, uint112 baseFee, uint8 liquidityfeeRate); - - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "invalid system fee receiver"); - feeReceiver = _feeReceiver; - } - - function _updateProtocolFee(address _token, uint112 _protocolFee) internal { - require(tokenInfos[_token].isRegistered, "token not registered"); - tokenInfos[_token].protocolFee = _protocolFee; - } - - function _updatePenaltyLnCollateral(address _token, uint112 _penaltyLnCollateral) internal { - require(tokenInfos[_token].isRegistered, "token not registered"); - tokenInfos[_token].penaltyLnCollateral = _penaltyLnCollateral; - } - - function providerPause(address sourceToken) external { - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - lnProviders[providerKey].pause = true; - } - - function providerUnpause(address sourceToken) external { - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - lnProviders[providerKey].pause = false; - } - - // lnProvider can register or update its configure by using this function - // * `margin` is the increased value of the deposited margin - function updateProviderFeeAndMargin( - address sourceToken, - uint112 margin, - uint112 baseFee, - uint8 liquidityFeeRate - ) external payable { - TokenInfo memory tokenInfo = tokenInfos[sourceToken]; - require(tokenInfo.isRegistered, "token is not registered"); - - bytes32 providerKey = getProviderKey(msg.sender, sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - - LnProviderConfigure memory config = LnProviderConfigure( - // the margin can be only increased here - margin + providerInfo.config.margin, - baseFee, - liquidityFeeRate); - - lnProviders[providerKey].config = config; - - if (sourceToken == address(0)) { - require(msg.value == margin, "invalid margin value"); - } else { - if (margin > 0) { - _safeTransferFrom(sourceToken, msg.sender, address(this), margin); - } - } - emit LnProviderUpdated(msg.sender, sourceToken, config.margin, baseFee, liquidityFeeRate); - } - - function _registerToken( - address sourceToken, - address targetToken, - uint112 protocolFee, - uint112 penaltyLnCollateral, - uint8 sourceDecimals, - uint8 targetDecimals - ) internal { - tokenInfos[sourceToken] = TokenInfo( - targetToken, - protocolFee, - penaltyLnCollateral, - sourceDecimals, - targetDecimals, - true - ); - } - - function calculateProviderFee(LnProviderConfigure memory config, uint112 amount) internal pure returns(uint256) { - return uint256(config.baseFee) + uint256(config.liquidityFeeRate) * uint256(amount) / LIQUIDITY_FEE_RATE_BASE; - } - - // the fee user should paid when transfer. - // totalFee = providerFee + protocolFee - // providerFee = provider.baseFee + provider.liquidityFeeRate * amount - function totalFee(address provider, address sourceToken, uint112 amount) external view returns(uint256) { - bytes32 providerKey = getProviderKey(provider, sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - uint256 providerFee = calculateProviderFee(providerInfo.config, amount); - return providerFee + tokenInfos[sourceToken].protocolFee; - } - - // This function transfers tokens from the user to LnProvider and generates a proof on the source chain. - // The snapshot represents the state of the LN bridge for this LnProvider, obtained by the off-chain indexer. - // If the chain state is updated and does not match the snapshot state, the transaction will be reverted. - // 1. the state(lastTransferId, fee, margin) must match snapshot - // 2. transferId not exist - function transferAndLockMargin( - Snapshot calldata snapshot, - uint112 amount, - address receiver - ) external payable { - require(amount > 0, "invalid amount"); - - bytes32 providerKey = getProviderKey(snapshot.provider, snapshot.sourceToken); - LnProviderInfo memory providerInfo = lnProviders[providerKey]; - - require(!providerInfo.pause, "provider paused"); - - TokenInfo memory tokenInfo = tokenInfos[snapshot.sourceToken]; - - uint256 providerFee = calculateProviderFee(providerInfo.config, amount); - - // Note: this requirement is not enough to ensure that the lnProvider's margin is enough because there maybe some frozen margins in other transfers - require(providerInfo.config.margin >= amount + tokenInfo.penaltyLnCollateral + uint112(providerFee), "amount not valid"); - - // the chain state not match snapshot - require(providerInfo.lastTransferId == snapshot.transferId, "snapshot expired"); - require(snapshot.totalFee >= tokenInfo.protocolFee + providerFee, "fee is invalid"); - require(snapshot.depositedMargin <= providerInfo.config.margin, "margin updated"); - - uint256 targetAmount = uint256(amount) * 10**tokenInfo.targetDecimals / 10**tokenInfo.sourceDecimals; - require(targetAmount < MAX_TRANSFER_AMOUNT, "overflow amount"); - uint64 timestamp = uint64(block.timestamp); - bytes32 transferId = keccak256(abi.encodePacked( - snapshot.transferId, - snapshot.provider, - snapshot.sourceToken, - tokenInfo.targetToken, - receiver, - timestamp, - uint112(targetAmount))); - require(lockInfos[transferId].amountWithFeeAndPenalty == 0, "transferId exist"); - lockInfos[transferId] = LockInfo(amount + tokenInfo.penaltyLnCollateral + uint112(providerFee), false); - - // update the state to prevent other transfers using the same snapshot - lnProviders[providerKey].lastTransferId = transferId; - - if (snapshot.sourceToken == address(0)) { - require(amount + snapshot.totalFee == msg.value, "amount unmatched"); - _safeTransferNative(snapshot.provider, amount + providerFee); - if (tokenInfo.protocolFee > 0) { - _safeTransferNative(feeReceiver, tokenInfo.protocolFee); - } - uint256 refund = snapshot.totalFee - tokenInfo.protocolFee - providerFee; - if ( refund > 0 ) { - _safeTransferNative(msg.sender, refund); - } - } else { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - snapshot.provider, - amount + providerFee - ); - if (tokenInfo.protocolFee > 0) { - _safeTransferFrom( - snapshot.sourceToken, - msg.sender, - feeReceiver, - tokenInfo.protocolFee - ); - } - } - emit TokenLocked( - transferId, - snapshot.provider, - snapshot.sourceToken, - amount, - uint112(providerFee), - timestamp, - receiver); - } - - // this slash is called by remote message - // the token should be sent to the slasher who slash and finish the transfer on target chain. - // latestSlashTransferId is the latest slashed transfer trusted from the target chain, and the current slash transfer cannot be executed before the latestSlash transfer. - // after slash, the margin of lnProvider need to be updated - function _slash( - bytes32 latestSlashTransferId, - bytes32 transferId, - address sourceToken, - address provider, - address slasher - ) internal { - // check lastTransfer - // ensure last slash transfer(checked on target chain) has been slashed - LockInfo memory lastLockInfo = lockInfos[latestSlashTransferId]; - require(lastLockInfo.hasSlashed || latestSlashTransferId == INIT_SLASH_TRANSFER_ID, "latest slash transfer invalid"); - LockInfo memory lockInfo = lockInfos[transferId]; - - // ensure transfer exist and not slashed yet - require(!lockInfo.hasSlashed, "transfer has been slashed"); - require(lockInfo.amountWithFeeAndPenalty > 0, "lnBridgeSource:invalid transferId"); - - bytes32 providerKey = getProviderKey(provider, sourceToken); - - LnProviderInfo memory lnProvider = lnProviders[providerKey]; - lockInfos[transferId].hasSlashed = true; - // transfer token to the slasher - uint256 slashAmount = lockInfo.amountWithFeeAndPenalty; - require(lnProvider.config.margin >= slashAmount, "margin not enough"); - uint112 updatedMargin = lnProvider.config.margin - uint112(slashAmount); - lnProviders[providerKey].config.margin = updatedMargin; - - if (sourceToken == address(0)) { - _safeTransferNative(slasher, slashAmount); - } else { - _safeTransfer(sourceToken, slasher, slashAmount); - } - - emit Slash(transferId, provider, sourceToken, updatedMargin, slasher); - } - - // lastTransfer is the latest slash transfer, all transfer must be relayed or slashed - // if user use the snapshot before this transaction to send cross-chain transfer, it should be reverted because this `_withdrawMargin` will decrease margin. - function _withdrawMargin( - bytes32 latestSlashTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) internal { - // check the latest slash transfer - // ensure latest slash tranfer(verified on target chain) has been slashed on source chain - LockInfo memory lastRefundLockInfo = lockInfos[latestSlashTransferId]; - require(lastRefundLockInfo.hasSlashed || latestSlashTransferId == INIT_SLASH_TRANSFER_ID, "latest slash transfer invalid"); - - // use this condition to ensure that the withdraw message is sent by the provider - // the parameter provider is the message sender of this remote withdraw call - bytes32 providerKey = getProviderKey(provider, sourceToken); - LnProviderInfo memory lnProvider = lnProviders[providerKey]; - - // ensure all transfer has finished - require(lnProvider.lastTransferId == lastTransferId, "invalid last transferid"); - require(lnProvider.config.margin >= amount, "margin not enough"); - uint112 updatedMargin = lnProvider.config.margin - amount; - lnProviders[providerKey].config.margin = updatedMargin; - if (sourceToken == address(0)) { - _safeTransferNative(provider, amount); - } else { - _safeTransfer(sourceToken, provider, amount); - } - emit LiquidityWithdrawn(provider, sourceToken, updatedMargin); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/ZkSync2EthSource.sol -// License-Identifier: MIT - - - -contract ZkSync2EthSource is Initializable, LnAccessController, LnOppositeBridgeSource { - uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); - address public remoteBridge; - address public remoteBridgeAlias; - - receive() external payable {} - - modifier onlyRemoteBridge() { - require(msg.sender == remoteBridgeAlias, "invalid remote caller"); - _; - } - - function initialize(address dao) public initializer { - _initialize(dao); - _setFeeReceiver(dao); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function updateProtocolFee(address token, uint112 _protocolFee) external onlyDao { - _updateProtocolFee(token, _protocolFee); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - remoteBridgeAlias = address(uint160(_remoteBridge) + offset); - } - - function setRemoteBridgeAlias(address _remoteBridgeAlias) external onlyDao { - remoteBridgeAlias = _remoteBridgeAlias; - } - - function registerToken( - address sourceToken, - address targetToken, - uint112 protocolFee, - uint112 penaltyLnCollateral, - uint8 sourceDecimals, - uint8 targetDecimals - ) external onlyOperator { - _registerToken(sourceToken, targetToken, protocolFee, penaltyLnCollateral, sourceDecimals, targetDecimals); - } - - function slash( - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) external onlyRemoteBridge whenNotPaused { - _slash(latestSlashTransferId, transferId, sourceToken, provider, slasher); - } - - function withdrawMargin( - bytes32 latestSlashTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) external onlyRemoteBridge whenNotPaused { - _withdrawMargin(latestSlashTransferId, lastTransferId, provider, sourceToken, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/ZkSync2EthTarget.sol b/helix-contract/flatten/lnv2/ZkSync2EthTarget.sol deleted file mode 100644 index 53d52b19..00000000 --- a/helix-contract/flatten/lnv2/ZkSync2EthTarget.sol +++ /dev/null @@ -1,1931 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 8/11/2023 - **/ - -pragma solidity ^0.8.10; - -// 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/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/ln/base/LnAccessController.sol -// License-Identifier: MIT - - -/// @title LnAccessController -/// @notice LnAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LnAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File contracts/ln/interface/ILnOppositeBridgeSource.sol -// License-Identifier: MIT - - -interface ILnOppositeBridgeSource { - function slash( - bytes32 lastRefundTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) external; - - function withdrawMargin( - bytes32 lastRefundTransferId, - bytes32 lastTransferId, - address provider, - address sourceToken, - uint112 amount - ) external; -} - -// 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/ln/base/LnBridgeHelper.sol -// License-Identifier: MIT - -contract LnBridgeHelper { - bytes32 constant public INIT_SLASH_TRANSFER_ID = bytes32(uint256(1)); - - struct TransferParameter { - bytes32 previousTransferId; - address provider; - address sourceToken; - address targetToken; - uint112 amount; - uint64 timestamp; - address receiver; - } - - 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))), "lnBridgeHelper: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))), "lnBridgeHelper:transferFrom token failed"); - } - - function _safeTransferNative( - address receiver, - uint256 amount - ) internal { - (bool success,) = payable(receiver).call{value: amount}(""); - require(success, "lnBridgeHelper:transfer native token failed"); - } - - function getProviderKey(address provider, address sourceToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken - )); - } - - function getDefaultProviderKey(address provider, address sourceToken, address targetToken) pure public returns(bytes32) { - return keccak256(abi.encodePacked( - provider, - sourceToken, - targetToken - )); - } -} - -// File contracts/ln/base/LnOppositeBridgeTarget.sol -// License-Identifier: MIT - - -contract LnOppositeBridgeTarget is LnBridgeHelper { - uint256 constant public MIN_REFUND_TIMESTAMP = 30 * 60; - - // if slasher == address(0), this FillTransfer is relayed by lnProvider - // otherwise, this FillTransfer is slashed by slasher - // if there is no slash transfer before, then it's latestSlashTransferId is assigned by INIT_SLASH_TRANSFER_ID, a special flag - struct SlashInfo { - address provider; - address sourceToken; - address slasher; - } - - // transferId => latest slash transfer Id - mapping(bytes32 => bytes32) public fillTransfers; - // transferId => Slash info - mapping(bytes32 => SlashInfo) public slashInfos; - - event TransferFilled(bytes32 transferId, address slasher); - - // if slasher is nonzero, then it's a slash fill transfer - function _checkPreviousAndFillTransfer( - bytes32 transferId, - bytes32 previousTransferId - ) internal { - // the first fill transfer, we fill the INIT_SLASH_TRANSFER_ID as the latest slash transferId - if (previousTransferId == bytes32(0)) { - fillTransfers[transferId] = INIT_SLASH_TRANSFER_ID; - } else { - // Find the previous slash fill, it is a slash fill if the slasher is not zero address. - bytes32 previousLatestSlashTransferId = fillTransfers[previousTransferId]; - require(previousLatestSlashTransferId != bytes32(0), "previous fill not exist"); - - SlashInfo memory previousSlashInfo = slashInfos[previousTransferId]; - // we use latestSlashTransferId to store the latest slash transferId - // if previous.slasher != 0, then previous is slashed - // if previous.slasher == 0, then previous is not slashed - bytes32 latestSlashTransferId = previousSlashInfo.slasher != address(0) ? previousTransferId : previousLatestSlashTransferId; - - fillTransfers[transferId] = latestSlashTransferId; - } - } - - // fill transfer - // 1. if transfer is not slashed or relayed, LnProvider relay message to fill the transfer, and the transfer finished on target chain - // 2. if transfer is timeout and not processed, slasher(any account) can fill the transfer and request slash - // if it's filled by slasher, we store the address of the slasher - // expectedTransferId used to ensure the parameter is the same as on source chain - // some cases - // 1) If transferId is not exist on source chain, it'll be rejected by source chain when shashed. - // 2) If transferId exist on source chain. We have the same hash process on source and target chain, so the previousTransferId is trusted. - // 2.1) If transferId is the first transfer Id of this provider, then previousTransferId is zero and the latestSlashTransferId is INIT_SLASH_TRANSFER_ID - // 2.2) If transferId is not the first transfer, then it's latestSlashTransferId has the next two scenarios - // * the previousTransfer is a slash transfer, then latestSlashTransferId is previousTransferId - // * the previousTransfer is a normal relayed transfer, then latestSlashTransferId is previousTransfer's latestSlashTransferId - // I. transferId is trusted => previousTransferId is trusted => previousTransfer.previousTransferId is trusted => ... => firstTransfer is trusted - // II. transferId is trusted => previousTransferId is trusted => latestSlashTransferId is trusted if previousTransfer is a slash transfer - // III. Both I and II => latestSlashTransferId is trusted if previousTransfer is normal relayed tranfer - function _fillTransfer( - TransferParameter calldata params, - bytes32 expectedTransferId - ) internal { - bytes32 transferId = keccak256(abi.encodePacked( - params.previousTransferId, - params.provider, - params.sourceToken, - params.targetToken, - params.receiver, - params.timestamp, - params.amount)); - require(expectedTransferId == transferId, "check expected transferId failed"); - // Make sure this transfer was never filled before - require(fillTransfers[transferId] == bytes32(0), "fill exist"); - - _checkPreviousAndFillTransfer(transferId, params.previousTransferId); - - if (params.targetToken == address(0)) { - require(msg.value >= params.amount, "invalid amount"); - _safeTransferNative(params.receiver, params.amount); - } else { - _safeTransferFrom(params.targetToken, msg.sender, params.receiver, uint256(params.amount)); - } - } - - function transferAndReleaseMargin( - TransferParameter calldata params, - bytes32 expectedTransferId - ) payable external { - // normal relay message, fill slasher as zero - require(params.provider == msg.sender, "invalid provider"); - _fillTransfer(params, expectedTransferId); - - emit TransferFilled(expectedTransferId, address(0)); - } - - // The condition for slash is that the transfer has timed out - // Meanwhile we need to request a slash transaction to the source chain to withdraw the LnProvider's margin - // On the source chain, we need to verify all the transfers before has been relayed or slashed. - // So we needs to carry the the previous shash transferId to ensure that the slash is continuous. - function _slashAndRemoteRefund( - TransferParameter calldata params, - bytes32 expectedTransferId - ) internal returns(bytes memory message) { - require(block.timestamp > params.timestamp + MIN_REFUND_TIMESTAMP, "slash time not expired"); - _fillTransfer(params, expectedTransferId); - - // slasher = msg.sender - slashInfos[expectedTransferId] = SlashInfo(params.provider, params.sourceToken, msg.sender); - - // Do not slash `transferId` in source chain unless `latestSlashTransferId` has been slashed - message = _encodeSlashCall( - fillTransfers[expectedTransferId], - expectedTransferId, - params.provider, - params.sourceToken, - msg.sender - ); - emit TransferFilled(expectedTransferId, msg.sender); - } - - // we use this to verify that the transfer has been slashed by user and it can resend the slash request - function _retrySlashAndRemoteRefund(bytes32 transferId) internal view returns(bytes memory message) { - bytes32 latestSlashTransferId = fillTransfers[transferId]; - // transfer must be filled - require(latestSlashTransferId != bytes32(0), "invalid transfer id"); - // transfer must be slashed - SlashInfo memory slashInfo = slashInfos[transferId]; - require(slashInfo.slasher != address(0), "slasher not exist"); - message = _encodeSlashCall( - latestSlashTransferId, - transferId, - slashInfo.provider, - slashInfo.sourceToken, - slashInfo.slasher - ); - } - - function _encodeSlashCall( - bytes32 latestSlashTransferId, - bytes32 transferId, - address provider, - address sourceToken, - address slasher - ) internal pure returns(bytes memory) { - return abi.encodeWithSelector( - ILnOppositeBridgeSource.slash.selector, - latestSlashTransferId, - transferId, - provider, - sourceToken, - slasher - ); - } - - function _requestWithdrawMargin( - bytes32 lastTransferId, - address sourceToken, - uint112 amount - ) internal view returns(bytes memory message) { - bytes32 latestSlashTransferId = fillTransfers[lastTransferId]; - require(latestSlashTransferId != bytes32(0), "invalid last transfer"); - - return abi.encodeWithSelector( - ILnOppositeBridgeSource.withdrawMargin.selector, - latestSlashTransferId, - lastTransferId, - msg.sender, - sourceToken, - amount - ); - } -} - -// File contracts/ln/interface/IZksyncMailbox.sol -// License-Identifier: MIT - -interface IMailbox { - function requestL2Transaction( - address _contractL2, - uint256 _l2Value, - bytes calldata _calldata, - uint256 _l2GasLimit, - uint256 _l2GasPerPubdataByteLimit, - bytes[] calldata _factoryDeps, - address _refundRecipient - ) external payable returns (bytes32 canonicalTxHash); - - // this function is used to calculate the fee on L2 - function l2TransactionBaseCost( - uint256 _gasPrice, - uint256 _l2GasLimit, - uint256 _l2GasPerPubdataByteLimit - ) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/ln/ZkSync2EthTarget.sol -// License-Identifier: MIT - - - - -contract ZkSync2EthTarget is Initializable, LnAccessController, LnOppositeBridgeTarget { - IMailbox public mailbox; - address public remoteBridge; - - event WithdrawMargin(bytes32 lastTransferId, uint112 amount); - - receive() external payable {} - - function initialize(address _dao, address _mailBox) public initializer { - mailbox = IMailbox(_mailBox); - _initialize(_dao); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - function l2Fee( - uint256 gasPrice, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) external view returns(uint256) { - return mailbox.l2TransactionBaseCost(gasPrice, l2GasLimit, l2GasPerPubdataByteLimit); - } - - function _sendMessage( - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit, - bytes memory message, - uint256 prepaid - ) internal returns(bytes32) { - return mailbox.requestL2Transaction{ value: prepaid }( - remoteBridge, - 0, - message, - l2GasLimit, - l2GasPerPubdataByteLimit, - new bytes[](0), - msg.sender - ); - } - - function slashAndRemoteRefund( - TransferParameter calldata params, - bytes32 expectedTransferId, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) payable external whenNotPaused { - bytes memory refundCallMessage = _slashAndRemoteRefund( - params, - expectedTransferId - ); - uint256 valueUsed = address(0) == params.targetToken ? params.amount : 0; - _sendMessage(l2GasLimit, l2GasPerPubdataByteLimit, refundCallMessage, msg.value - valueUsed); - } - - function retryRemoteRefund( - bytes32 transferId, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) payable external whenNotPaused { - bytes memory refundCallMessage = _retrySlashAndRemoteRefund(transferId); - _sendMessage(l2GasLimit, l2GasPerPubdataByteLimit, refundCallMessage, msg.value); - } - - function requestWithdrawMargin( - bytes32 lastTransferId, - address sourceToken, - uint112 amount, - uint256 l2GasLimit, - uint256 l2GasPerPubdataByteLimit - ) payable external whenNotPaused { - bytes memory cancelWithdrawMarginCall = _requestWithdrawMargin( - lastTransferId, - sourceToken, - amount - ); - _sendMessage(l2GasLimit, l2GasPerPubdataByteLimit, cancelWithdrawMarginCall, msg.value); - emit WithdrawMargin(lastTransferId, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/debugMessager.sol b/helix-contract/flatten/lnv2/debugMessager.sol index 1a84be5f..a57dcc78 100644 --- a/helix-contract/flatten/lnv2/debugMessager.sol +++ b/helix-contract/flatten/lnv2/debugMessager.sol @@ -14,10 +14,10 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 10/10/2023 + * 10/17/2023 **/ -pragma solidity ^0.8.10; +pragma solidity ^0.8.17; // File @zeppelin-solidity/contracts/token/ERC20/IERC20.sol@v4.7.3 // License-Identifier: MIT @@ -209,7 +209,6 @@ library LnBridgeHelper { // File contracts/ln/interface/ILnDefaultBridgeTarget.sol // License-Identifier: MIT - interface ILnDefaultBridgeTarget { function slash( LnBridgeHelper.TransferParameter memory params, @@ -233,7 +232,6 @@ interface ILnDefaultBridgeTarget { // File contracts/ln/interface/ILnOppositeBridgeSource.sol // License-Identifier: MIT - interface ILnOppositeBridgeSource { function slash( bytes32 lastRefundTransferId, diff --git a/helix-contract/flatten/lp/LpSub2EthBridge.sol b/helix-contract/flatten/lp/LpSub2EthBridge.sol deleted file mode 100644 index 8e4836c3..00000000 --- a/helix-contract/flatten/lp/LpSub2EthBridge.sol +++ /dev/null @@ -1,1992 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 2/10/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/mapping-token/interfaces/IHelixMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixMessageEndpoint { - function sendMessage(address receiver, bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IHelixSub2EthMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixSub2EthMessageEndpoint is IHelixMessageEndpoint { - function fee() external view returns (uint256); - function currentDeliveredMessageId() external view returns (uint256); - function isMessageDelivered(uint256 messageId) external view returns (bool); -} - -// 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 @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// File contracts/mapping-token/v2/lp/base/LpAccessController.sol -// License-Identifier: MIT - - -/// @title LpAccessController -/// @notice LpAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LpAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/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/mapping-token/v2/lp/base/LpBridgeHelper.sol -// License-Identifier: MIT - -contract LpBridgeHelper { - 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))), "lpBridgeHelper: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))), "lpBridgeHelper:transferFrom token failed"); - } -} - -// File contracts/mapping-token/v2/lp/base/LpBridgeBacking.sol -// License-Identifier: MIT - - - -/// @title LpBridgeBacking -/// @notice LpBridgeBacking is a contract to help user lock token and then trigger remote chain issuing -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LpBridgeBacking is LpBridgeHelper { - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - uint32 constant public INVALID_TOKEN_INDEX = type(uint32).max; - // the registered token info - // localToken and remoteToken is the pair of erc20 token addresses - // helixFee is charged by system, if it's bigger then half of user's fee, descrease it to the half - // remoteChainId is the remote block.chainid - // remoteIsNative is true when the remoteToken is the remote wrapped native token - struct TokenInfo { - address localToken; - address remoteToken; - uint112 helixFee; - uint64 remoteChainId; - uint8 localDecimals; - uint8 remoteDecimals; - bool remoteIsNative; - } - // registered token info - TokenInfo[] public tokens; - // each time cross chain transfer, amount and fee can't be larger than type(uint112).max - struct LockInfo { - uint32 tokenIndex; - uint112 amount; - uint112 fee; - } - mapping(bytes32 => LockInfo) public lockInfos; - address public feeReceiver; - uint32 public wTokenIndex = INVALID_TOKEN_INDEX; - - event TokenLocked( - uint64 toChainId, - bool isNative, - bool issuingNative, - uint256 nonce, - bytes32 transferId, - address token, - uint112 amount, - uint112 fee, - address receiver); - event FeeUpdated(bytes32 transferId, uint256 fee); - event LiquidityWithdrawn(bytes32 transferId, address receiver); - - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "lpBridgeBacking:invalid helix fee receiver"); - feeReceiver = _feeReceiver; - } - - function _updateHelixFee(uint32 _tokenIndex, uint112 _helixFee) internal { - require(_tokenIndex < tokens.length, "lpBridgeBacking:invalid token index"); - tokens[_tokenIndex].helixFee = _helixFee; - } - - function _setwTokenIndex(uint32 _wTokenIndex) internal { - wTokenIndex = _wTokenIndex; - } - - function _registerToken( - address localToken, - address remoteToken, - uint112 helixFee, - uint64 remoteChainId, - uint8 localDecimals, - uint8 remoteDecimals, - bool remoteIsNative - ) internal { - tokens.push(TokenInfo(localToken, remoteToken, helixFee, remoteChainId, localDecimals, remoteDecimals, remoteIsNative)); - } - - function _lockAndRemoteIssuing( - bool lockNative, - uint256 nonce, - uint32 tokenIndex, - uint112 amount, - uint112 fee, - address receiver, - bool issuingNative - ) internal returns(TokenInfo memory tokenInfo) { - tokenInfo = tokens[tokenIndex]; - require(fee > tokenInfo.helixFee && amount > 0, "lpBridgeBacking:fee or amount is not enough"); - require(!issuingNative || tokenInfo.remoteIsNative, "lpBridgeBacking:remote not native"); - uint256 remoteAmount = uint256(amount) * 10**tokenInfo.remoteDecimals / 10**tokenInfo.localDecimals; - require(remoteAmount < MAX_TRANSFER_AMOUNT, "lpBridgeBacking:overflow amount"); - bytes32 transferId = keccak256(abi.encodePacked( - nonce, - issuingNative, - tokenInfo.remoteToken, - msg.sender, - receiver, - uint112(remoteAmount), - uint64(block.chainid), - tokenInfo.remoteChainId)); - require(lockInfos[transferId].amount == 0, "lpBridgeBacking:transferId exist"); - lockInfos[transferId] = LockInfo(tokenIndex, amount, fee); - emit TokenLocked(tokenInfo.remoteChainId, lockNative, issuingNative, nonce, transferId, tokenInfo.localToken, amount, fee, receiver); - } - - function lockAndRemoteIssuing( - uint256 nonce, - address receiver, - uint112 amount, - uint112 fee, - uint32 tokenIndex, - bool issuingNative - ) external { - require(tokens.length > tokenIndex, "lpBridgeBacking:token not registered"); - TokenInfo memory info = _lockAndRemoteIssuing(false, nonce, tokenIndex, amount, fee, receiver, issuingNative); - _safeTransferFrom(info.localToken, msg.sender, address(this), amount + fee); - } - - function lockNativeAndRemoteIssuing( - uint112 amount, - uint112 fee, - address receiver, - uint256 nonce, - bool issuingNative - ) external payable { - require(amount + fee == msg.value, "lpBridgeBacking:amount unmatched"); - require(wTokenIndex != INVALID_TOKEN_INDEX, "lpBridgeBacking:not support"); - TokenInfo memory info = _lockAndRemoteIssuing(true, nonce, wTokenIndex, amount, fee, receiver, issuingNative); - IWToken(info.localToken).deposit{value: amount + fee}(); - } - - function _increaseFee(bytes32 transferId, uint256 fee) internal returns(uint32 tokenIndex) { - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.amount > 0 && lockInfo.tokenIndex < tokens.length, "lpBridgeBacking:invalid transferId"); - uint256 newFee = lockInfo.fee + fee; - require(newFee < MAX_TRANSFER_AMOUNT, "lpBridgeBacking:fee too large"); - lockInfos[transferId].fee = uint112(newFee); - tokenIndex = lockInfo.tokenIndex; - emit FeeUpdated(transferId, newFee); - } - - function increaseFee(bytes32 transferId, uint256 fee) external { - uint32 tokenIndex = _increaseFee(transferId, fee); - TokenInfo memory tokenInfo = tokens[tokenIndex]; - _safeTransferFrom(tokenInfo.localToken, msg.sender, address(this), fee); - } - - function increaseNativeFee(bytes32 transferId) external payable { - uint32 tokenIndex = _increaseFee(transferId, msg.value); - require(tokenIndex == wTokenIndex && wTokenIndex != INVALID_TOKEN_INDEX, "lpBridgeBacking:invalid token index"); - TokenInfo memory tokenInfo = tokens[tokenIndex]; - IWToken(tokenInfo.localToken).deposit{value: msg.value}(); - } - - // we require the same token to withdrawn - function _withdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) internal { - require(transferIds.length > 0, "lpBridgeBacking:invalid transferIds size"); - uint32 tokenIndex = lockInfos[transferIds[0]].tokenIndex; - require(tokenIndex < tokens.length, "lpBridgeBacking:out of token size"); - uint256 amount = 0; - uint256 fee = 0; - for (uint i = 0; i < transferIds.length; i++) { - bytes32 transferId = transferIds[i]; - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.amount > 0 && lockInfo.tokenIndex < tokens.length, "lpBridgeBacking:invalid transferId"); - require(lockInfo.tokenIndex == tokenIndex, "lpBridgeBacking:invalid tokenindex"); - //can't delete lockInfos directly - lockInfos[transferId].tokenIndex = INVALID_TOKEN_INDEX; - amount += lockInfo.amount; - fee += lockInfo.fee; - emit LiquidityWithdrawn(transferId, receiver); - } - TokenInfo memory tokenInfo = tokens[tokenIndex]; - uint256 helixFee = transferIds.length * tokenInfo.helixFee; - if (helixFee > fee / 2) { - helixFee = fee / 2; - } - uint256 lpFee = amount + fee - helixFee; - if (withdrawNative && tokenIndex == wTokenIndex) { - IWToken(tokenInfo.localToken).withdraw(lpFee); - payable(receiver).transfer(lpFee); - } else { - _safeTransfer(tokenInfo.localToken, receiver, lpFee); - } - _safeTransfer(tokenInfo.localToken, feeReceiver, helixFee); - } - - function tokenLength() external view returns (uint) { - return tokens.length; - } -} - -// File contracts/mapping-token/v2/lp/interface/ILpBridgeBacking.sol -// License-Identifier: MIT - - -interface ILpBridgeBacking { - function withdrawLiquidity(bytes32[] memory hashes, bool withdrawNative, address liquidityProvider) external; -} - -// File contracts/mapping-token/v2/lp/base/LpBridgeIssuing.sol -// License-Identifier: MIT - - -contract LpBridgeIssuing is LpBridgeHelper { - mapping(bytes32 => address) public issuedMessages; - - event TransferRelayed(bytes32 transferId, address relayer); - - function relay( - uint256 nonce, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId, - bool issuingNative - ) payable external { - bytes32 transferId = keccak256(abi.encodePacked(nonce, issuingNative, token, sender, receiver, amount, sourceChainId, uint64(block.chainid))); - require(issuedMessages[transferId] == address(0), "lpBridgeIssuing:message exist"); - issuedMessages[transferId] = msg.sender; - if (issuingNative) { - require(msg.value == amount, "lpBridgeIssuing:invalid amount"); - payable(receiver).transfer(amount); - } else { - _safeTransferFrom(token, msg.sender, receiver, uint256(amount)); - } - emit TransferRelayed(transferId, msg.sender); - } - - // only lpProvider can request withdraw liquidity - function _encodeWithdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver) internal view returns(bytes memory) { - for (uint idx = 0; idx < transferIds.length; idx++) { - address lpProvider = issuedMessages[transferIds[idx]]; - require(lpProvider == msg.sender, "invalid lpProvider"); - } - return abi.encodeWithSelector(ILpBridgeBacking.withdrawLiquidity.selector, transferIds, withdrawNative, receiver); - } - - // we only allowed token sender or receiver cancel the transaction - function _cancelIssuing( - uint256 nonce, - bool issuingNative, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId - ) internal returns(bytes32 transferId) { - require(sender == msg.sender || receiver == msg.sender, "lpBridgeIssuing:only sender or receiver allowed"); - transferId = keccak256(abi.encodePacked(nonce, issuingNative, token, sender, receiver, amount, sourceChainId, uint64(block.chainid))); - if (issuedMessages[transferId] == msg.sender) { - return transferId; - } - require(issuedMessages[transferId] == address(0), "lpBridgeIssuing:message exist"); - issuedMessages[transferId] = msg.sender; - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/lp/LpSub2EthBridge.sol -// License-Identifier: MIT - - - - - -contract LpSub2EthBridge is Initializable, LpAccessController, LpBridgeBacking, LpBridgeIssuing { - address public localEndpoint; - address public remoteEndpoint; - address public remoteBridge; - - event TransferCanceled(bytes32 transferId, address sender); - - receive() external payable {} - - modifier onlyEndpoint() { - require(localEndpoint == msg.sender, "LpSub2EthBridge:invalid endpoint"); - _; - } - - function fee() external view returns(uint256) { - return IHelixSub2EthMessageEndpoint(localEndpoint).fee(); - } - - function _sendMessage(bytes memory message, uint256 prepaid) internal returns(uint256) { - uint256 bridgeFee = IHelixSub2EthMessageEndpoint(localEndpoint).fee(); - require(prepaid >= bridgeFee, "backing:the fee is not enough"); - if (prepaid > bridgeFee) { - // refund fee to msgSender - payable(msg.sender).transfer(prepaid - bridgeFee); - } - uint256 transferId = IHelixSub2EthMessageEndpoint(localEndpoint).sendMessage{value: bridgeFee}( - remoteBridge, - message); - return transferId; - } - - function initialize(address _localEndpoint, address _remoteEndpoint, address dao) public initializer { - localEndpoint = _localEndpoint; - remoteEndpoint = _remoteEndpoint; - _initialize(dao); - _setFeeReceiver(dao); - } - - function updateMessageEndpoint(address _localEndpoint, address _remoteEndpoint) external onlyDao { - localEndpoint = _localEndpoint; - remoteEndpoint = _remoteEndpoint; - } - - function setwTokenIndex(uint32 _wTokenIndex) external onlyDao { - _setwTokenIndex(_wTokenIndex); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function updateHelixFee(uint32 _tokenIndex, uint112 _helixFee) external onlyDao { - _updateHelixFee(_tokenIndex, _helixFee); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - // backing mode called - function registerToken( - address local, - address remote, - uint112 helixFee, - uint32 remoteChainId, - uint8 localDecimals, - uint8 remoteDecimals, - bool remoteIsNative - ) external onlyDao { - _registerToken(local, remote, helixFee, remoteChainId, localDecimals, remoteDecimals, remoteIsNative); - } - - function withdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) external onlyEndpoint whenNotPaused { - _withdrawLiquidity(transferIds, withdrawNative, receiver); - } - - function requestWithdrawLiquidity(bytes32[] memory transferIds, bool withdrawNative, address receiver) payable external whenNotPaused { - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, receiver); - _sendMessage(withdrawCall, msg.value); - } - - function requestCancelIssuing( - uint256 nonce, - bool issuingNative, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId, - bool withdrawNative - ) payable external whenNotPaused { - bytes32 transferId = _cancelIssuing(nonce, issuingNative, token, sender, receiver, amount, sourceChainId); - bytes32[] memory transferIds = new bytes32[](1); - transferIds[0] = transferId; - // return token to the source sender - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, sender); - _sendMessage(withdrawCall, msg.value); - emit TransferCanceled(transferId, msg.sender); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/lp/LpSub2SubBridge.sol b/helix-contract/flatten/lp/LpSub2SubBridge.sol deleted file mode 100644 index 4596d9f9..00000000 --- a/helix-contract/flatten/lp/LpSub2SubBridge.sol +++ /dev/null @@ -1,2002 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 2/10/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/mapping-token/interfaces/IHelixMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixMessageEndpoint { - function sendMessage(address receiver, bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IHelixSub2SubMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixSub2SubMessageEndpoint is IHelixMessageEndpoint { - function fee() external view returns (uint256); - function lastDeliveredMessageId() external view returns (uint256); - function isMessageDelivered(uint256 messageId) external view returns(bool); - function sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address receiver, - bytes calldata encoded) external payable returns (uint256); -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/lp/base/LpAccessController.sol -// License-Identifier: MIT - - -/// @title LpAccessController -/// @notice LpAccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LpAccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - modifier onlyDao() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "lpBridge:Bad dao role"); - _; - } - - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "lpBridge:Bad operator role"); - _; - } - - function _initialize(address dao) internal { - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, dao); - _setupRole(OPERATOR_ROLE, msg.sender); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// 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/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/mapping-token/v2/lp/base/LpBridgeHelper.sol -// License-Identifier: MIT - -contract LpBridgeHelper { - 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))), "lpBridgeHelper: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))), "lpBridgeHelper:transferFrom token failed"); - } -} - -// File contracts/mapping-token/v2/lp/base/LpBridgeBacking.sol -// License-Identifier: MIT - - - -/// @title LpBridgeBacking -/// @notice LpBridgeBacking is a contract to help user lock token and then trigger remote chain issuing -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract LpBridgeBacking is LpBridgeHelper { - uint256 constant public MAX_TRANSFER_AMOUNT = type(uint112).max; - uint32 constant public INVALID_TOKEN_INDEX = type(uint32).max; - // the registered token info - // localToken and remoteToken is the pair of erc20 token addresses - // helixFee is charged by system, if it's bigger then half of user's fee, descrease it to the half - // remoteChainId is the remote block.chainid - // remoteIsNative is true when the remoteToken is the remote wrapped native token - struct TokenInfo { - address localToken; - address remoteToken; - uint112 helixFee; - uint64 remoteChainId; - uint8 localDecimals; - uint8 remoteDecimals; - bool remoteIsNative; - } - // registered token info - TokenInfo[] public tokens; - // each time cross chain transfer, amount and fee can't be larger than type(uint112).max - struct LockInfo { - uint32 tokenIndex; - uint112 amount; - uint112 fee; - } - mapping(bytes32 => LockInfo) public lockInfos; - address public feeReceiver; - uint32 public wTokenIndex = INVALID_TOKEN_INDEX; - - event TokenLocked( - uint64 toChainId, - bool isNative, - bool issuingNative, - uint256 nonce, - bytes32 transferId, - address token, - uint112 amount, - uint112 fee, - address receiver); - event FeeUpdated(bytes32 transferId, uint256 fee); - event LiquidityWithdrawn(bytes32 transferId, address receiver); - - function _setFeeReceiver(address _feeReceiver) internal { - require(_feeReceiver != address(this), "lpBridgeBacking:invalid helix fee receiver"); - feeReceiver = _feeReceiver; - } - - function _updateHelixFee(uint32 _tokenIndex, uint112 _helixFee) internal { - require(_tokenIndex < tokens.length, "lpBridgeBacking:invalid token index"); - tokens[_tokenIndex].helixFee = _helixFee; - } - - function _setwTokenIndex(uint32 _wTokenIndex) internal { - wTokenIndex = _wTokenIndex; - } - - function _registerToken( - address localToken, - address remoteToken, - uint112 helixFee, - uint64 remoteChainId, - uint8 localDecimals, - uint8 remoteDecimals, - bool remoteIsNative - ) internal { - tokens.push(TokenInfo(localToken, remoteToken, helixFee, remoteChainId, localDecimals, remoteDecimals, remoteIsNative)); - } - - function _lockAndRemoteIssuing( - bool lockNative, - uint256 nonce, - uint32 tokenIndex, - uint112 amount, - uint112 fee, - address receiver, - bool issuingNative - ) internal returns(TokenInfo memory tokenInfo) { - tokenInfo = tokens[tokenIndex]; - require(fee > tokenInfo.helixFee && amount > 0, "lpBridgeBacking:fee or amount is not enough"); - require(!issuingNative || tokenInfo.remoteIsNative, "lpBridgeBacking:remote not native"); - uint256 remoteAmount = uint256(amount) * 10**tokenInfo.remoteDecimals / 10**tokenInfo.localDecimals; - require(remoteAmount < MAX_TRANSFER_AMOUNT, "lpBridgeBacking:overflow amount"); - bytes32 transferId = keccak256(abi.encodePacked( - nonce, - issuingNative, - tokenInfo.remoteToken, - msg.sender, - receiver, - uint112(remoteAmount), - uint64(block.chainid), - tokenInfo.remoteChainId)); - require(lockInfos[transferId].amount == 0, "lpBridgeBacking:transferId exist"); - lockInfos[transferId] = LockInfo(tokenIndex, amount, fee); - emit TokenLocked(tokenInfo.remoteChainId, lockNative, issuingNative, nonce, transferId, tokenInfo.localToken, amount, fee, receiver); - } - - function lockAndRemoteIssuing( - uint256 nonce, - address receiver, - uint112 amount, - uint112 fee, - uint32 tokenIndex, - bool issuingNative - ) external { - require(tokens.length > tokenIndex, "lpBridgeBacking:token not registered"); - TokenInfo memory info = _lockAndRemoteIssuing(false, nonce, tokenIndex, amount, fee, receiver, issuingNative); - _safeTransferFrom(info.localToken, msg.sender, address(this), amount + fee); - } - - function lockNativeAndRemoteIssuing( - uint112 amount, - uint112 fee, - address receiver, - uint256 nonce, - bool issuingNative - ) external payable { - require(amount + fee == msg.value, "lpBridgeBacking:amount unmatched"); - require(wTokenIndex != INVALID_TOKEN_INDEX, "lpBridgeBacking:not support"); - TokenInfo memory info = _lockAndRemoteIssuing(true, nonce, wTokenIndex, amount, fee, receiver, issuingNative); - IWToken(info.localToken).deposit{value: amount + fee}(); - } - - function _increaseFee(bytes32 transferId, uint256 fee) internal returns(uint32 tokenIndex) { - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.amount > 0 && lockInfo.tokenIndex < tokens.length, "lpBridgeBacking:invalid transferId"); - uint256 newFee = lockInfo.fee + fee; - require(newFee < MAX_TRANSFER_AMOUNT, "lpBridgeBacking:fee too large"); - lockInfos[transferId].fee = uint112(newFee); - tokenIndex = lockInfo.tokenIndex; - emit FeeUpdated(transferId, newFee); - } - - function increaseFee(bytes32 transferId, uint256 fee) external { - uint32 tokenIndex = _increaseFee(transferId, fee); - TokenInfo memory tokenInfo = tokens[tokenIndex]; - _safeTransferFrom(tokenInfo.localToken, msg.sender, address(this), fee); - } - - function increaseNativeFee(bytes32 transferId) external payable { - uint32 tokenIndex = _increaseFee(transferId, msg.value); - require(tokenIndex == wTokenIndex && wTokenIndex != INVALID_TOKEN_INDEX, "lpBridgeBacking:invalid token index"); - TokenInfo memory tokenInfo = tokens[tokenIndex]; - IWToken(tokenInfo.localToken).deposit{value: msg.value}(); - } - - // we require the same token to withdrawn - function _withdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) internal { - require(transferIds.length > 0, "lpBridgeBacking:invalid transferIds size"); - uint32 tokenIndex = lockInfos[transferIds[0]].tokenIndex; - require(tokenIndex < tokens.length, "lpBridgeBacking:out of token size"); - uint256 amount = 0; - uint256 fee = 0; - for (uint i = 0; i < transferIds.length; i++) { - bytes32 transferId = transferIds[i]; - LockInfo memory lockInfo = lockInfos[transferId]; - require(lockInfo.amount > 0 && lockInfo.tokenIndex < tokens.length, "lpBridgeBacking:invalid transferId"); - require(lockInfo.tokenIndex == tokenIndex, "lpBridgeBacking:invalid tokenindex"); - //can't delete lockInfos directly - lockInfos[transferId].tokenIndex = INVALID_TOKEN_INDEX; - amount += lockInfo.amount; - fee += lockInfo.fee; - emit LiquidityWithdrawn(transferId, receiver); - } - TokenInfo memory tokenInfo = tokens[tokenIndex]; - uint256 helixFee = transferIds.length * tokenInfo.helixFee; - if (helixFee > fee / 2) { - helixFee = fee / 2; - } - uint256 lpFee = amount + fee - helixFee; - if (withdrawNative && tokenIndex == wTokenIndex) { - IWToken(tokenInfo.localToken).withdraw(lpFee); - payable(receiver).transfer(lpFee); - } else { - _safeTransfer(tokenInfo.localToken, receiver, lpFee); - } - _safeTransfer(tokenInfo.localToken, feeReceiver, helixFee); - } - - function tokenLength() external view returns (uint) { - return tokens.length; - } -} - -// File contracts/mapping-token/v2/lp/interface/ILpBridgeBacking.sol -// License-Identifier: MIT - - -interface ILpBridgeBacking { - function withdrawLiquidity(bytes32[] memory hashes, bool withdrawNative, address liquidityProvider) external; -} - -// File contracts/mapping-token/v2/lp/base/LpBridgeIssuing.sol -// License-Identifier: MIT - - -contract LpBridgeIssuing is LpBridgeHelper { - mapping(bytes32 => address) public issuedMessages; - - event TransferRelayed(bytes32 transferId, address relayer); - - function relay( - uint256 nonce, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId, - bool issuingNative - ) payable external { - bytes32 transferId = keccak256(abi.encodePacked(nonce, issuingNative, token, sender, receiver, amount, sourceChainId, uint64(block.chainid))); - require(issuedMessages[transferId] == address(0), "lpBridgeIssuing:message exist"); - issuedMessages[transferId] = msg.sender; - if (issuingNative) { - require(msg.value == amount, "lpBridgeIssuing:invalid amount"); - payable(receiver).transfer(amount); - } else { - _safeTransferFrom(token, msg.sender, receiver, uint256(amount)); - } - emit TransferRelayed(transferId, msg.sender); - } - - // only lpProvider can request withdraw liquidity - function _encodeWithdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver) internal view returns(bytes memory) { - for (uint idx = 0; idx < transferIds.length; idx++) { - address lpProvider = issuedMessages[transferIds[idx]]; - require(lpProvider == msg.sender, "invalid lpProvider"); - } - return abi.encodeWithSelector(ILpBridgeBacking.withdrawLiquidity.selector, transferIds, withdrawNative, receiver); - } - - // we only allowed token sender or receiver cancel the transaction - function _cancelIssuing( - uint256 nonce, - bool issuingNative, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId - ) internal returns(bytes32 transferId) { - require(sender == msg.sender || receiver == msg.sender, "lpBridgeIssuing:only sender or receiver allowed"); - transferId = keccak256(abi.encodePacked(nonce, issuingNative, token, sender, receiver, amount, sourceChainId, uint64(block.chainid))); - if (issuedMessages[transferId] == msg.sender) { - return transferId; - } - require(issuedMessages[transferId] == address(0), "lpBridgeIssuing:message exist"); - issuedMessages[transferId] = msg.sender; - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/lp/LpSub2SubBridge.sol -// License-Identifier: MIT - - - - - -contract LpSub2SubBridge is Initializable, LpAccessController, LpBridgeBacking, LpBridgeIssuing { - address localEndpoint; - address remoteEndpoint; - address remoteBridge; - - event TransferCanceled(bytes32 transferId, address sender); - - receive() external payable {} - - modifier onlyEndpoint() { - require(localEndpoint == msg.sender, "LpSub2SubBridge:invalid endpoint"); - _; - } - - function fee() external view returns(uint256) { - return IHelixSub2SubMessageEndpoint(localEndpoint).fee(); - } - - function _sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - bytes memory message, - uint256 prepaid) internal returns(uint256) { - uint256 bridgeFee = IHelixSub2SubMessageEndpoint(localEndpoint).fee(); - require(prepaid >= bridgeFee, "backing:the fee is not enough"); - if (prepaid > bridgeFee) { - // refund fee to msgSender - payable(msg.sender).transfer(prepaid - bridgeFee); - } - uint256 transferId = IHelixSub2SubMessageEndpoint(localEndpoint).sendMessage{value: bridgeFee}( - remoteSpecVersion, - remoteReceiveGasLimit, - remoteBridge, - message); - return transferId; - } - - function initialize(address _localEndpoint, address _remoteEndpoint, address dao) public initializer { - localEndpoint = _localEndpoint; - remoteEndpoint = _remoteEndpoint; - _initialize(dao); - _setFeeReceiver(dao); - } - - - function setwTokenIndex(uint32 _wTokenIndex) external onlyDao { - _setwTokenIndex(_wTokenIndex); - } - - function updateFeeReceiver(address _receiver) external onlyDao { - _setFeeReceiver(_receiver); - } - - function setRemoteBridge(address _remoteBridge) external onlyDao { - remoteBridge = _remoteBridge; - } - - // backing mode called - function registerToken( - address local, - address remote, - uint112 helixFee, - uint32 remoteChainId, - uint8 localDecimals, - uint8 remoteDecimals, - bool remoteIsNative - ) external onlyDao { - _registerToken(local, remote, helixFee, remoteChainId, localDecimals, remoteDecimals, remoteIsNative); - } - - function withdrawLiquidity( - bytes32[] memory transferIds, - bool withdrawNative, - address receiver - ) external onlyEndpoint whenNotPaused { - _withdrawLiquidity(transferIds, withdrawNative, receiver); - } - - function requestWithdrawLiquidity( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - bytes32[] memory transferIds, - bool withdrawNative, - address receiver) payable external whenNotPaused { - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, receiver); - _sendMessage(remoteSpecVersion, remoteReceiveGasLimit, withdrawCall, msg.value); - } - - function requestCancelIssuing( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - uint256 nonce, - bool issuingNative, - address token, - address sender, - address receiver, - uint112 amount, - uint64 sourceChainId, - bool withdrawNative - ) payable external whenNotPaused { - bytes32 transferId = _cancelIssuing(nonce, issuingNative, token, sender, receiver, amount, sourceChainId); - bytes32[] memory transferIds = new bytes32[](1); - transferIds[0] = transferId; - // return token to the source sender - bytes memory withdrawCall = _encodeWithdrawLiquidity(transferIds, withdrawNative, sender); - _sendMessage(remoteSpecVersion, remoteReceiveGasLimit, withdrawCall, msg.value); - emit TransferCanceled(transferId, msg.sender); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/DarwiniaSub2EthMessageEndpoint.sol b/helix-contract/flatten/sub2eth/DarwiniaSub2EthMessageEndpoint.sol deleted file mode 100644 index 56d6e9ea..00000000 --- a/helix-contract/flatten/sub2eth/DarwiniaSub2EthMessageEndpoint.sol +++ /dev/null @@ -1,1324 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 5/12/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/mapping-token/interfaces/IInboundLane.sol -// License-Identifier: MIT - - -interface IInboundLane { - struct RelayersRange { - uint64 front; - uint64 back; - } - - struct InboundLaneNonce { - uint64 last_confirmed_nonce; - uint64 last_delivered_nonce; - RelayersRange relayer_range; - } - - function inboundLaneNonce() view external returns(InboundLaneNonce memory); - function encodeMessageKey(uint64 nonce) view external returns(uint256); -} - -// File contracts/mapping-token/interfaces/IOutboundLane.sol -// License-Identifier: MIT - - -interface IOutboundLane { - struct OutboundLaneNonce { - uint64 latest_received_nonce; - uint64 latest_generated_nonce; - uint64 oldest_unpruned_nonce; - } - - function outboundLaneNonce() view external returns(OutboundLaneNonce memory); - - function send_message(address targetContract, bytes calldata encoded) external payable returns (uint64); -} - -// File contracts/mapping-token/interfaces/ICrossChainFilter.sol -// License-Identifier: MIT - - -/** - * @title A interface for message layer to filter unsafe message - * @author echo - * @notice The app layer must implement the interface `ICrossChainFilter` - */ -interface ICrossChainFilter { - /** - * @notice Verify the source sender and payload of source chain messages, - * Generally, app layer cross-chain messages require validation of sourceAccount - * @param bridgedChainPosition The source chain position which send the message - * @param bridgedLanePosition The source lane position which send the message - * @param sourceAccount The source contract address which send the message - * @param payload The calldata which encoded by ABI Encoding - * @return Can call target contract if returns true - */ - function cross_chain_filter(uint32 bridgedChainPosition, uint32 bridgedLanePosition, address sourceAccount, bytes calldata payload) external view returns (bool); -} - -// File contracts/mapping-token/interfaces/IFeeMarket.sol -// License-Identifier: MIT - -pragma abicoder v2; - -interface IFeeMarket { - // Relayer which delivery the messages - struct DeliveredRelayer { - // relayer account - address relayer; - // encoded message key begin - uint256 begin; - // encoded message key end - uint256 end; - } - function market_fee() external view returns (uint256 fee); - - function assign(uint256 nonce) external payable returns(bool); - function settle(DeliveredRelayer[] calldata delivery_relayers, address confirm_relayer) external returns(bool); -} - -// File contracts/mapping-token/interfaces/IHelixApp.sol -// License-Identifier: MIT - - -interface IHelixAppSupportWithdrawFailed { - function handleUnlockFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; - function handleUnlockFailureFromRemoteNative( - uint256 messageId, - address sender, - uint256 amount - ) external; - function handleIssuingFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/AccessController.sol -// License-Identifier: MIT - - -contract AccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - bytes32 public constant CALLER_ROLE = keccak256("CALLER_ROLE"); - bytes32 public constant CALLEE_ROLE = keccak256("CALLEE_ROLE"); - - // access controller - // admin is helix Dao - modifier onlyAdmin() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "AccessController:Bad admin role"); - _; - } - - // operator - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "AccessController:Bad operator role"); - _; - } - - modifier onlyCaller() { - require(hasRole(CALLER_ROLE, msg.sender), "AccessController:Bad caller role"); - _; - } - - modifier onlyCallee() { - require(hasRole(CALLEE_ROLE, msg.sender), "AccessController:Bad callee role"); - _; - } - - function _initialize(address admin) internal { - _setRoleAdmin(CALLER_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(CALLEE_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, admin); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File contracts/mapping-token/v2/message-endpoints/DarwiniaSub2EthMessageEndpoint.sol -// License-Identifier: MIT - - - - - - -contract DarwiniaSub2EthMessageEndpoint is ICrossChainFilter, AccessController { - address immutable public inboundLane; - address immutable public outboundLane; - address immutable public feeMarket; - uint16 immutable public version; - - address public remoteEndpoint; - - constructor( - uint16 _version, - address _inboundLane, - address _outboundLane, - address _feeMarket - ) { - version = _version; - inboundLane = _inboundLane; - outboundLane = _outboundLane; - feeMarket = _feeMarket; - _initialize(msg.sender); - } - - modifier onlyInboundLane() { - require(inboundLane == msg.sender, "DarwiniaSub2EthMessageEndpoint:caller is not the inboundLane account"); - _; - } - - modifier onlyOutBoundLane() { - require(outboundLane == msg.sender, "DarwiniaSub2EthMessageEndpoint:caller is not the outboundLane account"); - _; - } - - function setRemoteEndpoint(address _remoteEndpoint) external onlyAdmin { - require(remoteEndpoint == address(0), "DarwiniaSub2EthMessageEndpoint:can only set once"); - remoteEndpoint = _remoteEndpoint; - } - - function cross_chain_filter( - uint32, - uint32, - address sourceAccount, - bytes calldata - ) external view returns (bool) { - return inboundLane == msg.sender && remoteEndpoint == sourceAccount; - } - - function fee() public view returns(uint256) { - return IFeeMarket(feeMarket).market_fee(); - } - - function nonceToMessageId(uint256 nonce) internal view returns(uint256) { - return (uint256(version) << 64) + nonce; - } - - function sendMessage(address receiver, bytes calldata message) external onlyCaller payable returns (uint256) { - bytes memory messageWithCaller = abi.encodeWithSelector( - DarwiniaSub2EthMessageEndpoint.recvMessage.selector, - receiver, - message - ); - uint256 nonce = IOutboundLane(outboundLane).send_message{value: msg.value}( - remoteEndpoint, - messageWithCaller - ); - return nonceToMessageId(nonce); - } - - function recvMessage( - address receiver, - bytes calldata message - ) external onlyInboundLane whenNotPaused { - require(hasRole(CALLEE_ROLE, receiver), "DarwiniaSub2EthMessageEndpoint:receiver is not callee"); - (bool result,) = receiver.call(message); - require(result, "DarwiniaSub2EthMessageEndpoint:call app failed"); - } - - // we use nonce as message id - function currentDeliveredMessageId() public view returns(uint256) { - IInboundLane.InboundLaneNonce memory inboundLaneNonce = IInboundLane(inboundLane).inboundLaneNonce(); - return nonceToMessageId(inboundLaneNonce.last_delivered_nonce + 1); - } - - function isMessageDelivered(uint256 messageId) public view returns (bool) { - IInboundLane.InboundLaneNonce memory inboundLaneNonce = IInboundLane(inboundLane).inboundLaneNonce(); - uint256 lastMessageNonce = inboundLaneNonce.last_delivered_nonce; - return messageId <= nonceToMessageId(lastMessageNonce); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/Erc20.sol b/helix-contract/flatten/sub2eth/Erc20.sol deleted file mode 100644 index db1113f0..00000000 --- a/helix-contract/flatten/sub2eth/Erc20.sol +++ /dev/null @@ -1,555 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 5/12/2023 - **/ - -pragma solidity ^0.8.10; - -// 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) - - -// CAUTION -// This version of SafeMath should only be used with Solidity 0.8 or later, -// because it relies on the compiler's built in overflow checks. - -/** - * @dev Wrappers over Solidity's arithmetic operations. - * - * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler - * now has built in overflow checking. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - return a + b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - return a * b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b <= a, errorMessage); - return a - b; - } - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a / b; - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a % b; - } - } -} - -// 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/access/Ownable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20.sol -// License-Identifier: MIT - - - -contract Erc20 is IERC20, Ownable { - using SafeMath for uint256; - - mapping (address => uint256) private _balances; - - mapping (address => mapping (address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string public name; - string public symbol; - uint8 public decimals; - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - _transferOwnership(_msgSender()); - } - - function totalSupply() public view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address account) public view override returns (uint256) { - return _balances[account]; - } - - function transfer(address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(msg.sender, recipient, amount); - return true; - } - - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _approve(msg.sender, spender, amount); - return true; - } - - function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(sender, recipient, amount); - _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")); - return true; - } - - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); - return true; - } - - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); - return true; - } - - function _transfer(address sender, address recipient, uint256 amount) internal virtual { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(sender, recipient, amount); - - _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); - _balances[recipient] = _balances[recipient].add(amount); - emit Transfer(sender, recipient, amount); - } - - // only factory contract can mint with the lock proof from ethereum - function mint(address account, uint256 amount) external onlyOwner { - _mint(account, amount); - } - - function burn(address account, uint256 amount) external { - if (account != msg.sender && owner() != msg.sender && _allowances[account][msg.sender] != type(uint256).max) { - _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: decreased allowance below zero")); - } - _burn(account, amount); - } - - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); - } - - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); - _totalSupply = _totalSupply.sub(amount); - emit Transfer(account, address(0), amount); - } - - function _approve(address owner, address spender, uint256 amount) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/Erc20Sub2EthBacking.sol b/helix-contract/flatten/sub2eth/Erc20Sub2EthBacking.sol deleted file mode 100644 index afa7b8c4..00000000 --- a/helix-contract/flatten/sub2eth/Erc20Sub2EthBacking.sol +++ /dev/null @@ -1,2105 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 5/12/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/utils/DailyLimit.sol -// License-Identifier: MIT - - -/// @title relay with daily limit - Allows the relay to mint token in a daily limit. -contract DailyLimit { - - event DailyLimitChange(address token, uint dailyLimit); - - mapping(address => uint) public dailyLimit; - // deprecated, slot for upgrade - mapping(address => uint) public _slotReserved; - mapping(address => uint) public spentToday; - - uint constant public SPEND_BIT_LENGTH = 192; - uint constant public LASTDAY_BIT_LENGTH = 64; - - /// ==== Internal functions ==== - - /// @dev Contract constructor sets initial owners, required number of confirmations and daily mint limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei, which can be mint without confirmations on a daily basis. - function _setDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - } - - /// @dev Allows to change the daily limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei. - function _changeDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - emit DailyLimitChange(_token, _dailyLimit); - } - - /// @dev Allows to change the daily limit. - /// @param token Token address. - /// @param amount Amount in wei. - function expendDailyLimit(address token, uint amount) - internal - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - require(amount <= dailyLimit[token], "DailyLimit: amount exceed daily limit"); - spentToday[token] = (block.timestamp << SPEND_BIT_LENGTH) + amount; - return; - } - require(lastspent + amount <= dailyLimit[token] && amount <= dailyLimit[token], "DailyLimit: exceed daily limit"); - spentToday[token] = spentInfo + amount; - } - - /// ==== Web3 call functions ==== - - /// @dev Returns maximum withdraw amount. - /// @param token Token address. - /// @return Returns amount. - function calcMaxWithdraw(address token) - public - view - returns (uint) - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - return dailyLimit[token]; - } - - if (dailyLimit[token] < lastspent) { - return 0; - } - - return dailyLimit[token] - lastspent; - } -} - -// File contracts/mapping-token/interfaces/IHelixApp.sol -// License-Identifier: MIT - - -interface IHelixAppSupportWithdrawFailed { - function handleUnlockFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; - function handleUnlockFailureFromRemoteNative( - uint256 messageId, - address sender, - uint256 amount - ) external; - function handleIssuingFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; -} - -// File contracts/mapping-token/interfaces/IBacking.sol -// License-Identifier: MIT - - -interface IBacking { - function unlockFromRemote( - address originalToken, - address recipient, - uint256 amount) external; -} - -interface IBackingSupportNative { - function unlockFromRemoteNative( - address recipient, - uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IGuard.sol -// License-Identifier: MIT - - -interface IGuard { - function deposit(uint256 id, address token, address recipient, uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IErc20MappingTokenFactory.sol -// License-Identifier: MIT - - -interface IErc20MappingTokenFactory { - function newErc20Contract( - address originalToken, - string memory bridgedChainName, - string memory name, - string memory symbol, - uint8 decimals, - uint256 dailyLimit - ) external returns (address mappingToken); - function issueMappingToken( - address originalToken, - address recipient, - uint256 amount - ) external; -} - -// File contracts/mapping-token/interfaces/IHelixMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixMessageEndpoint { - function sendMessage(address receiver, bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IHelixSub2EthMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixSub2EthMessageEndpoint is IHelixMessageEndpoint { - function fee() external view returns (uint256); - function currentDeliveredMessageId() external view returns (uint256); - function isMessageDelivered(uint256 messageId) external view returns (bool); -} - -// 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/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/AccessController.sol -// License-Identifier: MIT - - -contract AccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - bytes32 public constant CALLER_ROLE = keccak256("CALLER_ROLE"); - bytes32 public constant CALLEE_ROLE = keccak256("CALLEE_ROLE"); - - // access controller - // admin is helix Dao - modifier onlyAdmin() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "AccessController:Bad admin role"); - _; - } - - // operator - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "AccessController:Bad operator role"); - _; - } - - modifier onlyCaller() { - require(hasRole(CALLER_ROLE, msg.sender), "AccessController:Bad caller role"); - _; - } - - modifier onlyCallee() { - require(hasRole(CALLEE_ROLE, msg.sender), "AccessController:Bad callee role"); - _; - } - - function _initialize(address admin) internal { - _setRoleAdmin(CALLER_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(CALLEE_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, admin); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/Backing.sol -// License-Identifier: MIT - - -contract Backing is AccessController, Initializable { - address public messageEndpoint; - address public remoteMappingTokenFactory; - - uint256 internal locked; - modifier nonReentrant { - require(locked == 0, "backing: locked"); - locked = 1; - _; - locked = 0; - } - - modifier onlyMessageEndpoint() { - require(messageEndpoint == msg.sender, "Backing:Bad message handle"); - _; - } - - function initialize(address _messageEndpoint) public initializer { - messageEndpoint = _messageEndpoint; - _initialize(msg.sender); - } - - function _setMessageEndpoint(address _messageEndpoint) internal { - messageEndpoint = _messageEndpoint; - } - - function setRemoteMappingTokenFactory(address _remoteMappingTokenFactory) external onlyAdmin { - remoteMappingTokenFactory = _remoteMappingTokenFactory; - } -} - -// File @zeppelin-solidity/contracts/utils/structs/BitMaps.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol) - -/** - * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. - * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. - */ -library BitMaps { - struct BitMap { - mapping(uint256 => uint256) _data; - } - - /** - * @dev Returns whether the bit at `index` is set. - */ - function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - return bitmap._data[bucket] & mask != 0; - } - - /** - * @dev Sets the bit at `index` to the boolean `value`. - */ - function setTo( - BitMap storage bitmap, - uint256 index, - bool value - ) internal { - if (value) { - set(bitmap, index); - } else { - unset(bitmap, index); - } - } - - /** - * @dev Sets the bit at `index`. - */ - function set(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] |= mask; - } - - /** - * @dev Unsets the bit at `index`. - */ - function unset(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] &= ~mask; - } -} - -// 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/mapping-token/v2/erc20-mapping-protocol/Erc20Sub2EthBacking.sol -// License-Identifier: MIT - - - - - - - - - - -contract Erc20Sub2EthBacking is Backing, DailyLimit, IBacking { - struct LockedInfo { - bytes32 hash; - bool hasRefundForFailed; - } - address public guard; - uint256 public helixFee; - // This is the wrapped native token address - address public wToken; - - // (transferId => lockedInfo) - mapping(uint256 => LockedInfo) public lockedMessages; - BitMaps.BitMap unlockedTransferIds; - - event TokenLocked(uint256 transferId, bool isNative, address token, address sender, address recipient, uint256 amount, uint256 fee); - event TokenUnlocked(uint256 transferId, bool isNative, address token, address recipient, uint256 amount); - event RemoteIssuingFailure(uint256 refundId, uint256 transferId, address mappingToken, address originalSender, uint256 amount, uint256 fee); - event TokenUnlockedForFailed(uint256 transferId, bool isNative, address token, address recipient, uint256 amount); - - receive() external payable {} - - // !!! admin must check the nonce of the newEndpoint is larger than the old one - function setMessageEndpoint(address _messageEndpoint) external onlyAdmin { - _setMessageEndpoint(_messageEndpoint); - } - - function changeDailyLimit(address token, uint amount) public onlyAdmin { - _changeDailyLimit(token, amount); - } - - function setHelixFee(uint256 _helixFee) external onlyAdmin { - helixFee = _helixFee; - } - - function setNativeWrappedToken(address _wToken) external onlyAdmin { - wToken = _wToken; - } - - function updateGuard(address newGuard) external onlyAdmin { - guard = newGuard; - } - - function currentFee() external view returns(uint256) { - return IHelixSub2EthMessageEndpoint(messageEndpoint).fee() + helixFee; - } - - // we use messageId as transferId directly here - function _sendMessage(bytes memory message, uint256 prepaid) internal nonReentrant returns(uint256, uint256) { - uint256 bridgeFee = IHelixSub2EthMessageEndpoint(messageEndpoint).fee(); - uint256 totalFee = bridgeFee + helixFee; - require(prepaid >= totalFee, "backing:the fee is not enough"); - if (prepaid > totalFee) { - // refund fee to msgSender - payable(msg.sender).transfer(prepaid - totalFee); - } - uint256 transferId = IHelixSub2EthMessageEndpoint(messageEndpoint).sendMessage{value: bridgeFee}( - remoteMappingTokenFactory, - message); - return (transferId, totalFee); - } - - function _lockAndRemoteIssuing( - address token, - address recipient, - uint256 amount, - uint256 prepaid, - bool isNative - ) internal { - bytes memory issueMappingToken = abi.encodeWithSelector( - IErc20MappingTokenFactory.issueMappingToken.selector, - token, - recipient, - amount - ); - (uint256 transferId, uint256 fee) = _sendMessage(issueMappingToken, prepaid); - bytes32 lockMessageHash = hash(abi.encodePacked(transferId, token, msg.sender, amount)); - lockedMessages[transferId] = LockedInfo(lockMessageHash, false); - emit TokenLocked(transferId, isNative, token, msg.sender, recipient, amount, fee); - } - - /** - * @notice lock original token and issuing mapping token from bridged chain - * @dev maybe some tokens will take some fee when transfer - * @param token the original token address - * @param recipient the recipient who will receive the issued mapping token - * @param amount amount of the locked token - */ - function lockAndRemoteIssuing( - address token, - address recipient, - uint256 amount - ) external payable whenNotPaused { - uint256 balanceBefore = IERC20(token).balanceOf(address(this)); - require(IERC20(token).transferFrom(msg.sender, address(this), amount), "Backing:transfer tokens failed"); - uint256 balanceAfter = IERC20(token).balanceOf(address(this)); - require(balanceBefore + amount == balanceAfter, "Backing:Transfer amount is invalid"); - _lockAndRemoteIssuing(token, recipient, amount, msg.value, false); - } - - /** - * @notice lock original native token and issuing mapping token from bridged chain - * @dev maybe some tokens will take some fee when transfer - * @param recipient the recipient who will receive the issued mapping token - * @param amount amount of the locked token - */ - function lockAndRemoteIssuingNative( - address recipient, - uint256 amount - ) external payable whenNotPaused { - require(msg.value > amount, "Backing: msg.value must larger than amount"); - IWToken(wToken).deposit{value: amount}(); - _lockAndRemoteIssuing(wToken, recipient, amount, msg.value - amount, true); - } - - /** - * @notice this will be called by inboundLane when the remote mapping token burned and want to unlock the original token - * @param token the original token address - * @param recipient the recipient who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function unlockFromRemote( - address token, - address recipient, - uint256 amount - ) public onlyMessageEndpoint whenNotPaused { - uint256 transferId = IHelixSub2EthMessageEndpoint(messageEndpoint).currentDeliveredMessageId(); - require(BitMaps.get(unlockedTransferIds, transferId) == false, "Backing:message has been accepted"); - BitMaps.set(unlockedTransferIds, transferId); - expendDailyLimit(token, amount); - if (guard != address(0)) { - // see https://github.com/helix-bridge/contracts/issues/18 - uint allowance = IERC20(token).allowance(address(this), guard); - require(IERC20(token).approve(guard, allowance + amount), "Backing:approve token transfer to guard failed"); - IGuard(guard).deposit(transferId, token, recipient, amount); - } else { - require(IERC20(token).transfer(recipient, amount), "Backing:unlock transfer failed"); - } - emit TokenUnlocked(transferId, false, token, recipient, amount); - } - - /** - * @notice this will be called by inboundLane when the remote mapping token burned and want to unlock the original native token - * @param recipient the recipient who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function unlockFromRemoteNative( - address payable recipient, - uint256 amount - ) public onlyMessageEndpoint whenNotPaused { - expendDailyLimit(wToken, amount); - uint256 transferId = IHelixSub2EthMessageEndpoint(messageEndpoint).currentDeliveredMessageId(); - require(BitMaps.get(unlockedTransferIds, transferId) == false, "Backing:message has been accepted"); - BitMaps.set(unlockedTransferIds, transferId); - if (guard != address(0)) { - uint allowance = IERC20(wToken).allowance(address(this), guard); - require(IERC20(wToken).approve(guard, allowance + amount), "Backing:approve token transfer to guard failed"); - IGuard(guard).deposit(transferId, wToken, recipient, amount); - } else { - IWToken(wToken).withdraw(amount); - recipient.transfer(amount); - } - emit TokenUnlocked(transferId, true, wToken, recipient, amount); - } - - function remoteIssuingFailure( - uint256 transferId, - address mappingToken, - address originalSender, - uint256 amount - ) external payable whenNotPaused { - // must not exist in successful issue list - require(BitMaps.get(unlockedTransferIds, transferId) == false, "Backing:success message can't refund for failed"); - bool messageChecked = IHelixSub2EthMessageEndpoint(messageEndpoint).isMessageDelivered(transferId); - require(messageChecked, "Backing:the message is not checked by message layer"); - bytes memory unlockForFailed = abi.encodeWithSelector( - IHelixAppSupportWithdrawFailed.handleIssuingFailureFromRemote.selector, - transferId, - mappingToken, - originalSender, - amount - ); - (uint256 refundId, uint256 fee) = _sendMessage(unlockForFailed, msg.value); - emit RemoteIssuingFailure(refundId, transferId, mappingToken, originalSender, amount, fee); - } - - /** - * @notice this will be called by messageEndpoint when the remote issue failed and want to unlock the original token - * @param token the original token address - * @param originSender the origin sender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function _handleUnlockFailureFromRemote( - uint256 transferId, - address token, - address originSender, - uint256 amount - ) internal whenNotPaused { - LockedInfo memory lockedMessage = lockedMessages[transferId]; - require(lockedMessage.hasRefundForFailed == false, "Backing: the locked message has been refund"); - bytes32 messageHash = hash(abi.encodePacked(transferId, token, originSender, amount)); - require(lockedMessage.hash == messageHash, "Backing: message is not matched"); - lockedMessages[transferId].hasRefundForFailed = true; - } - - /** - * @notice this will be called by messageEndpoint when the remote issue failed and want to unlock the original token - * @param token the original token address - * @param originSender the origin sender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function handleUnlockFailureFromRemote( - uint256 transferId, - address token, - address originSender, - uint256 amount - ) external onlyMessageEndpoint { - _handleUnlockFailureFromRemote(transferId, token, originSender, amount); - require(IERC20(token).transfer(originSender, amount), "Backing:unlock transfer failed"); - emit TokenUnlockedForFailed(transferId, false, token, originSender, amount); - } - - /** - * @notice this will be called by messageEndpoint when the remote issue failed and want to unlock the original token - * @param originSender the origin sender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function handleUnlockFailureFromRemoteNative( - uint256 transferId, - address originSender, - uint256 amount - ) external onlyMessageEndpoint { - _handleUnlockFailureFromRemote(transferId, wToken, originSender, amount); - IWToken(wToken).withdraw(amount); - payable(originSender).transfer(amount); - emit TokenUnlockedForFailed(transferId, true, wToken, originSender, amount); - } - - /** - * @notice this should not be used unless there is a non-recoverable error in the bridge or the target chain - * we use this to protect user's asset from being locked up - */ - function rescueFunds( - address token, - address recipient, - uint256 amount - ) external onlyAdmin { - IERC20(token).transfer(recipient, amount); - } - - - function hash(bytes memory value) public pure returns (bytes32) { - return sha256(value); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/Erc20Sub2EthMappingTokenFactory.sol b/helix-contract/flatten/sub2eth/Erc20Sub2EthMappingTokenFactory.sol deleted file mode 100644 index ddafb873..00000000 --- a/helix-contract/flatten/sub2eth/Erc20Sub2EthMappingTokenFactory.sol +++ /dev/null @@ -1,2593 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 5/12/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/utils/DailyLimit.sol -// License-Identifier: MIT - - -/// @title relay with daily limit - Allows the relay to mint token in a daily limit. -contract DailyLimit { - - event DailyLimitChange(address token, uint dailyLimit); - - mapping(address => uint) public dailyLimit; - // deprecated, slot for upgrade - mapping(address => uint) public _slotReserved; - mapping(address => uint) public spentToday; - - uint constant public SPEND_BIT_LENGTH = 192; - uint constant public LASTDAY_BIT_LENGTH = 64; - - /// ==== Internal functions ==== - - /// @dev Contract constructor sets initial owners, required number of confirmations and daily mint limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei, which can be mint without confirmations on a daily basis. - function _setDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - } - - /// @dev Allows to change the daily limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei. - function _changeDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - emit DailyLimitChange(_token, _dailyLimit); - } - - /// @dev Allows to change the daily limit. - /// @param token Token address. - /// @param amount Amount in wei. - function expendDailyLimit(address token, uint amount) - internal - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - require(amount <= dailyLimit[token], "DailyLimit: amount exceed daily limit"); - spentToday[token] = (block.timestamp << SPEND_BIT_LENGTH) + amount; - return; - } - require(lastspent + amount <= dailyLimit[token] && amount <= dailyLimit[token], "DailyLimit: exceed daily limit"); - spentToday[token] = spentInfo + amount; - } - - /// ==== Web3 call functions ==== - - /// @dev Returns maximum withdraw amount. - /// @param token Token address. - /// @return Returns amount. - function calcMaxWithdraw(address token) - public - view - returns (uint) - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - return dailyLimit[token]; - } - - if (dailyLimit[token] < lastspent) { - return 0; - } - - return dailyLimit[token] - lastspent; - } -} - -// File contracts/mapping-token/interfaces/IBacking.sol -// License-Identifier: MIT - - -interface IBacking { - function unlockFromRemote( - address originalToken, - address recipient, - uint256 amount) external; -} - -interface IBackingSupportNative { - function unlockFromRemoteNative( - address recipient, - uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IHelixApp.sol -// License-Identifier: MIT - - -interface IHelixAppSupportWithdrawFailed { - function handleUnlockFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; - function handleUnlockFailureFromRemoteNative( - uint256 messageId, - address sender, - uint256 amount - ) external; - function handleIssuingFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; -} - -// File contracts/mapping-token/interfaces/IHelixMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixMessageEndpoint { - function sendMessage(address receiver, bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IHelixSub2EthMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixSub2EthMessageEndpoint is IHelixMessageEndpoint { - function fee() external view returns (uint256); - function currentDeliveredMessageId() external view returns (uint256); - function isMessageDelivered(uint256 messageId) external view returns (bool); -} - -// File contracts/mapping-token/interfaces/IGuard.sol -// License-Identifier: MIT - - -interface IGuard { - function deposit(uint256 id, address token, address recipient, uint256 amount) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/AccessController.sol -// License-Identifier: MIT - - -contract AccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - bytes32 public constant CALLER_ROLE = keccak256("CALLER_ROLE"); - bytes32 public constant CALLEE_ROLE = keccak256("CALLEE_ROLE"); - - // access controller - // admin is helix Dao - modifier onlyAdmin() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "AccessController:Bad admin role"); - _; - } - - // operator - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "AccessController:Bad operator role"); - _; - } - - modifier onlyCaller() { - require(hasRole(CALLER_ROLE, msg.sender), "AccessController:Bad caller role"); - _; - } - - modifier onlyCallee() { - require(hasRole(CALLEE_ROLE, msg.sender), "AccessController:Bad callee role"); - _; - } - - function _initialize(address admin) internal { - _setRoleAdmin(CALLER_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(CALLEE_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, admin); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @zeppelin-solidity/contracts/access/Ownable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/MappingTokenFactory.sol -// License-Identifier: MIT -// This is the Issuing Module(Mapping-token-factory) of the ethereum like bridge. -// We trust the inboundLane/outboundLane when we add them to the module. -// It means that each message from the inboundLane is verified correct and truthly from the sourceAccount. -// Only we need is to verify the sourceAccount is expected. And we add it to the Filter. - - - -contract MappingTokenFactory is AccessController, Initializable { - address[] public allMappingTokens; - // salt=>mappingToken, the salt is derived from origin token on backing chain - // so this is a mapping from origin to mapping token - mapping(bytes32 => address) public salt2MappingToken; - // mappingToken=>info the info is the original token info - // so this is a mapping from mappingToken to original token - mapping(address => address) public mappingToken2OriginalToken; - - address public messageEndpoint; - address public remoteBacking; - - uint256 internal locked; - modifier nonReentrant { - require(locked == 0, "MappingTokenFactory: locked"); - locked = 1; - _; - locked = 0; - } - - modifier onlyMessageEndpoint() { - require(messageEndpoint == msg.sender, "MappingTokenFactory:Bad message handle"); - _; - } - - function initialize(address _messageEndpoint) public initializer { - _setMessageEndpoint(_messageEndpoint); - _initialize(msg.sender); - } - - function _setMessageEndpoint(address _messageEndpoint) internal { - messageEndpoint = _messageEndpoint; - } - - function setRemoteBacking(address _remoteBacking) external onlyAdmin { - remoteBacking = _remoteBacking; - } - - function _transferMappingTokenOwnership(address mappingToken, address new_owner) internal { - Ownable(mappingToken).transferOwnership(new_owner); - } - - /** - * @notice add mapping-token address by owner - * @param salt the salt of the mapping token deployed - * @param originalToken the original token address - * @param mappingToken the mapping token address - */ - function _addMappingToken( - bytes32 salt, - address originalToken, - address mappingToken - ) internal { - // save the mapping tokens in an array so it can be listed - allMappingTokens.push(mappingToken); - // map the originToken to mappingInfo - salt2MappingToken[salt] = mappingToken; - // map the mappingToken to origin info - mappingToken2OriginalToken[mappingToken] = originalToken; - } - - // internal - function _deploy(bytes32 salt, bytes memory bytecodeWithInitdata) internal returns (address addr) { - assembly { - addr := create2(0, add(bytecodeWithInitdata, 0x20), mload(bytecodeWithInitdata), salt) - if iszero(extcodesize(addr)) { revert(0, 0) } - } - } - - function tokenLength() public view returns (uint) { - return allMappingTokens.length; - } - - function getMappingToken(address backingAddress, address originalToken) public view returns (address) { - bytes32 salt = keccak256(abi.encodePacked(backingAddress, originalToken)); - return salt2MappingToken[salt]; - } -} - -// 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) - - -// CAUTION -// This version of SafeMath should only be used with Solidity 0.8 or later, -// because it relies on the compiler's built in overflow checks. - -/** - * @dev Wrappers over Solidity's arithmetic operations. - * - * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler - * now has built in overflow checking. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - return a + b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - return a * b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b <= a, errorMessage); - return a - b; - } - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a / b; - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a % b; - } - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20.sol -// License-Identifier: MIT - - - -contract Erc20 is IERC20, Ownable { - using SafeMath for uint256; - - mapping (address => uint256) private _balances; - - mapping (address => mapping (address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string public name; - string public symbol; - uint8 public decimals; - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - _transferOwnership(_msgSender()); - } - - function totalSupply() public view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address account) public view override returns (uint256) { - return _balances[account]; - } - - function transfer(address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(msg.sender, recipient, amount); - return true; - } - - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _approve(msg.sender, spender, amount); - return true; - } - - function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(sender, recipient, amount); - _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")); - return true; - } - - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); - return true; - } - - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); - return true; - } - - function _transfer(address sender, address recipient, uint256 amount) internal virtual { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(sender, recipient, amount); - - _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); - _balances[recipient] = _balances[recipient].add(amount); - emit Transfer(sender, recipient, amount); - } - - // only factory contract can mint with the lock proof from ethereum - function mint(address account, uint256 amount) external onlyOwner { - _mint(account, amount); - } - - function burn(address account, uint256 amount) external { - if (account != msg.sender && owner() != msg.sender && _allowances[account][msg.sender] != type(uint256).max) { - _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: decreased allowance below zero")); - } - _burn(account, amount); - } - - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); - } - - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); - _totalSupply = _totalSupply.sub(amount); - emit Transfer(account, address(0), amount); - } - - function _approve(address owner, address spender, uint256 amount) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } -} - -// File @zeppelin-solidity/contracts/utils/structs/BitMaps.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol) - -/** - * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. - * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. - */ -library BitMaps { - struct BitMap { - mapping(uint256 => uint256) _data; - } - - /** - * @dev Returns whether the bit at `index` is set. - */ - function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - return bitmap._data[bucket] & mask != 0; - } - - /** - * @dev Sets the bit at `index` to the boolean `value`. - */ - function setTo( - BitMap storage bitmap, - uint256 index, - bool value - ) internal { - if (value) { - set(bitmap, index); - } else { - unset(bitmap, index); - } - } - - /** - * @dev Sets the bit at `index`. - */ - function set(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] |= mask; - } - - /** - * @dev Unsets the bit at `index`. - */ - function unset(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] &= ~mask; - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20Sub2EthMappingTokenFactory.sol -// License-Identifier: MIT -// This is the Issuing Module(Mapping-token-factory) of the ethereum like bridge. -// We trust the inboundLane/outboundLane when we add them to the module. -// It means that each message from the inboundLane is verified correct and truthly from the sourceAccount. -// Only we need is to verify the sourceAccount is expected. And we add it to the Filter. - - - - - - - - -contract Erc20Sub2EthMappingTokenFactory is DailyLimit, MappingTokenFactory { - struct BurnInfo { - bytes32 hash; - bool hasRefundForFailed; - } - // guard - address public guard; - uint256 public helixFee; - address xwToken; - - mapping(uint256 => BurnInfo) burnMessages; - BitMaps.BitMap issueMessages; - - event IssuingERC20Created(address originalToken, address mappingToken); - event BurnAndRemoteUnlocked(uint256 transferId, bool isNative, address sender, address recipient, address token, uint256 amount, uint256 fee); - event TokenRemintForFailed(uint256 transferId, address token, address recipient, uint256 amount); - event RemoteUnlockFailure(uint256 refundId, uint256 transferId, address originalToken, address originalSender, uint256 amount, uint256 fee); - - receive() external payable {} - - modifier verifyRemoteUnlockFailure(uint256 transferId) { - // must not exist in successful issue list - require(BitMaps.get(issueMessages, transferId) == false, "MappingTokenFactory:success message can't refund for failed"); - // must has been checked by message layer - bool messageChecked = IHelixSub2EthMessageEndpoint(messageEndpoint).isMessageDelivered(transferId); - require(messageChecked, "MappingTokenFactory:the message is not checked by message layer"); - _; - } - - /** - * @notice only admin can transfer the ownership of the mapping token from factory to other account - * generally we should not do this. When we encounter a non-recoverable error, we temporarily transfer the privileges to a maintenance account. - * @param mappingToken the address the mapping token - * @param new_owner the new owner of the mapping token - */ - function transferMappingTokenOwnership(address mappingToken, address new_owner) external onlyAdmin { - _transferMappingTokenOwnership(mappingToken, new_owner); - } - - function updateGuard(address newGuard) external onlyAdmin { - guard = newGuard; - } - - function changeDailyLimit(address mappingToken, uint amount) public onlyAdmin { - _changeDailyLimit(mappingToken, amount); - } - - // !!! admin must check the nonce of the newEndpoint is larger than the old one - function setMessageEndpoint(address _messageEndpoint) external onlyAdmin { - _setMessageEndpoint(_messageEndpoint); - } - - function setMappingNativeWrappedToken(address _xwToken) external onlyAdmin { - xwToken = _xwToken; - } - - function currentFee() external view returns(uint256) { - return IHelixSub2EthMessageEndpoint(messageEndpoint).fee() + helixFee; - } - - function _sendMessage(bytes memory message) internal nonReentrant returns(uint256, uint256) { - uint256 bridgeFee = IHelixSub2EthMessageEndpoint(messageEndpoint).fee(); - uint256 totalFee = bridgeFee + helixFee; - require(msg.value >= totalFee, "MappingTokenFactory:the fee is not enough"); - if (msg.value > totalFee) { - payable(msg.sender).transfer(msg.value - totalFee); - } - uint256 transferId = IHelixSub2EthMessageEndpoint(messageEndpoint).sendMessage{value: bridgeFee}( - remoteBacking, - message); - return (transferId, totalFee); - } - - /** - * @notice create new erc20 mapping contract, this can only be called by operator - * @param originalToken the original token address - * @param name the name of the original erc20 token - * @param symbol the symbol of the original erc20 token - * @param decimals the decimals of the original erc20 token - */ - function register( - address originalToken, - string memory bridgedChainName, - string memory name, - string memory symbol, - uint8 decimals, - uint256 dailyLimit - ) public onlyOperator whenNotPaused returns (address mappingToken) { - bytes32 salt = keccak256(abi.encodePacked(remoteBacking, originalToken)); - require(salt2MappingToken[salt] == address(0), "MappingTokenFactory:contract has been deployed"); - bytes memory bytecode = type(Erc20).creationCode; - bytes memory bytecodeWithInitdata = abi.encodePacked( - bytecode, - abi.encode( - string(abi.encodePacked(name, "[", bridgedChainName, ">")), - string(abi.encodePacked("x", symbol)), - decimals - )); - mappingToken = _deploy(salt, bytecodeWithInitdata); - _addMappingToken(salt, originalToken, mappingToken); - _changeDailyLimit(mappingToken, dailyLimit); - emit IssuingERC20Created(originalToken, mappingToken); - } - - /** - * @notice set erc20 mapping contract directly, this can be only called by admin - * @param originalToken the original token address - * @param mappingToken the mapping token address of the original erc20 token - * @param dailyLimit the daily limit of the mapping erc20 token - */ - function setMappingToken( - address originalToken, - address mappingToken, - uint256 dailyLimit - ) public onlyAdmin { - bytes32 salt = keccak256(abi.encodePacked(remoteBacking, originalToken)); - require(salt2MappingToken[salt] == address(0), "MappingTokenFactory:contract has been deployed"); - _addMappingToken(salt, originalToken, mappingToken); - _changeDailyLimit(mappingToken, dailyLimit); - emit IssuingERC20Created(originalToken, mappingToken); - } - - /** - * @notice issue mapping token, only can be called by inboundLane - * @param originalToken the original token address - * @param recipient the recipient of the issued mapping token - * @param amount the amount of the issued mapping token - */ - function issueMappingToken( - address originalToken, - address recipient, - uint256 amount - ) public onlyMessageEndpoint whenNotPaused { - address mappingToken = getMappingToken(remoteBacking, originalToken); - require(mappingToken != address(0), "MappingTokenFactory:mapping token has not created"); - require(amount > 0, "MappingTokenFactory:can not receive amount zero"); - uint256 transferId = IHelixSub2EthMessageEndpoint(messageEndpoint).currentDeliveredMessageId(); - expendDailyLimit(mappingToken, amount); - require(BitMaps.get(issueMessages, transferId) == false, "MappingTokenFactory:message has been accepted"); - BitMaps.set(issueMessages, transferId); - if (guard != address(0)) { - Erc20(mappingToken).mint(address(this), amount); - uint allowance = IERC20(mappingToken).allowance(address(this), guard); - require(IERC20(mappingToken).approve(guard, allowance + amount), "Backing:approve token transfer to guard failed"); - IGuard(guard).deposit(transferId, mappingToken, recipient, amount); - } else { - Erc20(mappingToken).mint(recipient, amount); - } - } - - function _burnAndRemoteUnlock( - address mappingToken, - address recipient, - uint256 amount, - bytes memory remoteUnlockCall, - bool isNative - ) internal whenNotPaused { - require(amount > 0, "MappingTokenFactory:can not transfer amount zero"); - // transfer to this and then burn - require(IERC20(mappingToken).transferFrom(msg.sender, address(this), amount), "MappingTokenFactory:transfer token failed"); - Erc20(mappingToken).burn(address(this), amount); - (uint256 transferId, uint256 fee) = _sendMessage(remoteUnlockCall); - require(burnMessages[transferId].hash == bytes32(0), "MappingTokenFactory: message exist"); - bytes32 messageHash = hash(abi.encodePacked(transferId, mappingToken, msg.sender, amount)); - burnMessages[transferId] = BurnInfo(messageHash, false); - emit BurnAndRemoteUnlocked(transferId, isNative, msg.sender, recipient, mappingToken, amount, fee); - } - - /** - * @notice burn mapping token and unlock remote original native token - * @param recipient the recipient of the remote unlocked token - * @param amount the amount of the burn and unlock - */ - function burnAndRemoteUnlockNative( - address recipient, - uint256 amount - ) external payable { - require(amount > 0, "MappingTokenFactory:can not transfer amount zero"); - address originalToken = mappingToken2OriginalToken[xwToken]; - require(originalToken != address(0), "MappingTokenFactory:token is not created by factory"); - bytes memory unlockFromRemoteNative = abi.encodeWithSelector( - IBackingSupportNative.unlockFromRemoteNative.selector, - recipient, - amount - ); - - _burnAndRemoteUnlock(xwToken, recipient, amount, unlockFromRemoteNative, true); - } - - /** - * @notice burn mapping token and unlock remote original token - * @param mappingToken the burt mapping token address - * @param recipient the recipient of the remote unlocked token - * @param amount the amount of the burn and unlock - */ - function burnAndRemoteUnlock( - address mappingToken, - address recipient, - uint256 amount - ) external payable { - require(amount > 0, "MappingTokenFactory:can not transfer amount zero"); - address originalToken = mappingToken2OriginalToken[mappingToken]; - require(originalToken != address(0), "MappingTokenFactory:token is not created by factory"); - bytes memory unlockFromRemote = abi.encodeWithSelector( - IBacking.unlockFromRemote.selector, - originalToken, - recipient, - amount - ); - - _burnAndRemoteUnlock(mappingToken, recipient, amount, unlockFromRemote, false); - } - - /** - * @notice send a unlock message to backing when issue mapping token faild to redeem original token. - * @param originalToken the original token address - * @param originalSender the originalSender of the remote unlocked token, must be the same as msg.send of the failed message. - * @param amount the amount of the failed issue token. - */ - function remoteUnlockFailure( - uint256 transferId, - address originalToken, - address originalSender, - uint256 amount - ) external payable verifyRemoteUnlockFailure(transferId) whenNotPaused { - bytes memory handleUnlockForFailed = abi.encodeWithSelector( - IHelixAppSupportWithdrawFailed.handleUnlockFailureFromRemote.selector, - transferId, - originalToken, - originalSender, - amount - ); - (uint256 refundId, uint256 fee) = _sendMessage(handleUnlockForFailed); - emit RemoteUnlockFailure(refundId, transferId, originalToken, originalSender, amount, fee); - } - - /** - * @notice send a unlock message to backing when issue mapping token faild to redeem original token. - * @param originalSender the originalSender of the remote unlocked token, must be the same as msg.send of the failed message. - * @param amount the amount of the failed issue token. - */ - function remoteUnlockFailureNative( - uint256 transferId, - address originalSender, - uint256 amount - ) external payable verifyRemoteUnlockFailure(transferId) whenNotPaused { - bytes memory handleUnlockForFailedNative = abi.encodeWithSelector( - IHelixAppSupportWithdrawFailed.handleUnlockFailureFromRemoteNative.selector, - transferId, - originalSender, - amount - ); - (uint256 refundId, uint256 fee) = _sendMessage(handleUnlockForFailedNative); - emit RemoteUnlockFailure(refundId, transferId, xwToken, originalSender, amount, fee); - } - - /** - * @notice this will be called by messageEndpoint when the remote backing unlock failed and want to unlock the mapping token - * @param token the original token address - * @param origin_sender the origin_sender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function handleIssuingFailureFromRemote( - uint256 transferId, - address token, - address origin_sender, - uint256 amount - ) external onlyMessageEndpoint whenNotPaused { - BurnInfo memory burnInfo = burnMessages[transferId]; - require(burnInfo.hasRefundForFailed == false, "Backing:the burn message has been refund"); - bytes32 messageHash = hash(abi.encodePacked(transferId, token, origin_sender, amount)); - require(burnInfo.hash == messageHash, "Backing:message is not matched"); - burnMessages[transferId].hasRefundForFailed = true; - Erc20(token).mint(origin_sender, amount); - emit TokenRemintForFailed(transferId, token, origin_sender, amount); - } - - function hash(bytes memory value) public pure returns (bytes32) { - return sha256(value); - } - - function rescueFunds( - address token, - address recipient, - uint256 amount - ) external onlyAdmin { - IERC20(token).transfer(recipient, amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/Guard.sol b/helix-contract/flatten/sub2eth/Guard.sol deleted file mode 100644 index e24d5b73..00000000 --- a/helix-contract/flatten/sub2eth/Guard.sol +++ /dev/null @@ -1,1207 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 5/12/2023 - **/ - -pragma solidity ^0.8.10; - -// 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) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/cryptography/ECDSA.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) - - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - enum RecoverError { - NoError, - InvalidSignature, - InvalidSignatureLength, - InvalidSignatureS, - InvalidSignatureV - } - - function _throwError(RecoverError error) private pure { - if (error == RecoverError.NoError) { - return; // no error: do nothing - } else if (error == RecoverError.InvalidSignature) { - revert("ECDSA: invalid signature"); - } else if (error == RecoverError.InvalidSignatureLength) { - revert("ECDSA: invalid signature length"); - } else if (error == RecoverError.InvalidSignatureS) { - revert("ECDSA: invalid signature 's' value"); - } else if (error == RecoverError.InvalidSignatureV) { - revert("ECDSA: invalid signature 'v' value"); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature` or error string. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - * - * Documentation for signature generation: - * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] - * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] - * - * _Available since v4.3._ - */ - function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { - if (signature.length == 65) { - bytes32 r; - bytes32 s; - uint8 v; - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - /// @solidity memory-safe-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - return tryRecover(hash, v, r, s); - } else { - return (address(0), RecoverError.InvalidSignatureLength); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - */ - function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, signature); - _throwError(error); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. - * - * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] - * - * _Available since v4.3._ - */ - function tryRecover( - bytes32 hash, - bytes32 r, - bytes32 vs - ) internal pure returns (address, RecoverError) { - bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); - uint8 v = uint8((uint256(vs) >> 255) + 27); - return tryRecover(hash, v, r, s); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. - * - * _Available since v4.2._ - */ - function recover( - bytes32 hash, - bytes32 r, - bytes32 vs - ) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, r, vs); - _throwError(error); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `v`, - * `r` and `s` signature fields separately. - * - * _Available since v4.3._ - */ - function tryRecover( - bytes32 hash, - uint8 v, - bytes32 r, - bytes32 s - ) internal pure returns (address, RecoverError) { - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { - return (address(0), RecoverError.InvalidSignatureS); - } - if (v != 27 && v != 28) { - return (address(0), RecoverError.InvalidSignatureV); - } - - // If the signature is valid (and not malleable), return the signer address - address signer = ecrecover(hash, v, r, s); - if (signer == address(0)) { - return (address(0), RecoverError.InvalidSignature); - } - - return (signer, RecoverError.NoError); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `v`, - * `r` and `s` signature fields separately. - */ - function recover( - bytes32 hash, - uint8 v, - bytes32 r, - bytes32 s - ) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, v, r, s); - _throwError(error); - return recovered; - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * produces hash corresponding to the one signed with the - * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] - * JSON-RPC method as part of EIP-191. - * - * See {recover}. - */ - function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } - - /** - * @dev Returns an Ethereum Signed Message, created from `s`. This - * produces hash corresponding to the one signed with the - * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] - * JSON-RPC method as part of EIP-191. - * - * See {recover}. - */ - function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); - } - - /** - * @dev Returns an Ethereum Signed Typed Data, created from a - * `domainSeparator` and a `structHash`. This produces hash corresponding - * to the one signed with the - * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] - * JSON-RPC method as part of EIP-712. - * - * See {recover}. - */ - function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); - } -} - -// File contracts/mapping-token/v2/GuardRegistry.sol -// License-Identifier: Apache-2.0 - -pragma experimental ABIEncoderV2; - -/** - * @title Manages a set of guards and a threshold to double-check BEEFY commitment - * @dev Stores the guards and a threshold - * @author echo - */ -contract GuardRegistry { - event AddedGuard(address guard); - event RemovedGuard(address guard); - event ChangedThreshold(uint256 threshold); - - // keccak256( - // "EIP712Domain(uint256 chainId,address verifyingContract)" - // ); - bytes32 internal constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; - - address internal constant SENTINEL_GUARDS = address(0x1); - - /** - * @dev Nonce to prevent replay of update operations - */ - uint256 public nonce; - /** - * @dev Store all guards in the linked list - */ - mapping(address => address) internal guards; - /** - * @dev Count of all guards - */ - uint256 internal guardCount; - /** - * @dev Number of required confirmations for update operations - */ - uint256 internal threshold; - - /** - * @dev Sets initial storage of contract. - * @param _guards List of Safe guards. - * @param _threshold Number of required confirmations for check commitment or change guards. - */ - function initialize(address[] memory _guards, uint256 _threshold) internal { - // Threshold can only be 0 at initialization. - // Check ensures that setup function can only be called once. - require(threshold == 0, "Guard: Guards have already been setup"); - // Validate that threshold is smaller than number of added guards. - require(_threshold <= _guards.length, "Guard: Threshold cannot exceed guard count"); - // There has to be at least one Safe guard. - require(_threshold >= 1, "Guard: Threshold needs to be greater than 0"); - // Initializing Safe guards. - address currentGuard = SENTINEL_GUARDS; - for (uint256 i = 0; i < _guards.length; i++) { - // Guard address cannot be null. - address guard = _guards[i]; - require(guard != address(0) && guard != SENTINEL_GUARDS && guard != address(this) && currentGuard != guard, "Guard: Invalid guard address provided"); - // No duplicate guards allowed. - require(guards[guard] == address(0), "Guard: Address is already an guard"); - guards[currentGuard] = guard; - currentGuard = guard; - emit AddedGuard(guard); - } - guards[currentGuard] = SENTINEL_GUARDS; - guardCount = _guards.length; - threshold = _threshold; - } - - /** - * @dev Allows to add a new guard to the registry and update the threshold at the same time. - * This can only be done via multi-sig. - * @notice Adds the guard `guard` to the registry and updates the threshold to `_threshold`. - * @param guard New guard address. - * @param _threshold New threshold. - * @param signatures The signatures of the guards which to add new guard and update the `threshold` . - */ - function addGuardWithThreshold( - address guard, - uint256 _threshold, - bytes[] memory signatures - ) public { - // Guard address cannot be null, the sentinel or the registry itself. - require(guard != address(0) && guard != SENTINEL_GUARDS && guard != address(this), "Guard: Invalid guard address provided"); - // No duplicate guards allowed. - require(guards[guard] == address(0), "Guard: Address is already an guard"); - verifyGuardSignatures(msg.sig, abi.encode(guard, _threshold), signatures); - guards[guard] = guards[SENTINEL_GUARDS]; - guards[SENTINEL_GUARDS] = guard; - guardCount++; - emit AddedGuard(guard); - // Change threshold if threshold was changed. - if (threshold != _threshold) _changeThreshold(_threshold); - } - - /** - * @dev Allows to remove an guard from the registry and update the threshold at the same time. - * This can only be done via multi-sig. - * @notice Removes the guard `guard` from the registry and updates the threshold to `_threshold`. - * @param prevGuard Guard that pointed to the guard to be removed in the linked list - * @param guard Guard address to be removed. - * @param _threshold New threshold. - * @param signatures The signatures of the guards which to remove a guard and update the `threshold` . - */ - function removeGuard( - address prevGuard, - address guard, - uint256 _threshold, - bytes[] memory signatures - ) public { - // Only allow to remove an guard, if threshold can still be reached. - require(guardCount - 1 >= _threshold, "Guard: Threshold cannot exceed guard count"); - // Validate guard address and check that it corresponds to guard index. - require(guard != address(0) && guard != SENTINEL_GUARDS, "Guard: Invalid guard address provided"); - require(guards[prevGuard] == guard, "Guard: Invalid prevGuard, guard pair provided"); - verifyGuardSignatures(msg.sig, abi.encode(prevGuard, guard, _threshold), signatures); - guards[prevGuard] = guards[guard]; - guards[guard] = address(0); - guardCount--; - emit RemovedGuard(guard); - // Change threshold if threshold was changed. - if (threshold != _threshold) _changeThreshold(_threshold); - } - - /** - * @dev Allows to swap/replace a guard from the registry with another address. - * This can only be done via multi-sig. - * @notice Replaces the guard `oldGuard` in the registry with `newGuard`. - * @param prevGuard guard that pointed to the guard to be replaced in the linked list - * @param oldGuard guard address to be replaced. - * @param newGuard New guard address. - * @param signatures The signatures of the guards which to swap/replace a guard and update the `threshold` . - */ - function swapGuard( - address prevGuard, - address oldGuard, - address newGuard, - bytes[] memory signatures - ) public { - // Guard address cannot be null, the sentinel or the registry itself. - require(newGuard != address(0) && newGuard != SENTINEL_GUARDS && newGuard != address(this), "Guard: Invalid guard address provided"); - // No duplicate guards allowed. - require(guards[newGuard] == address(0), "Guard: Address is already an guard"); - // Validate oldGuard address and check that it corresponds to guard index. - require(oldGuard != address(0) && oldGuard != SENTINEL_GUARDS, "Guard: Invalid guard address provided"); - require(guards[prevGuard] == oldGuard, "Guard: Invalid prevGuard, guard pair provided"); - verifyGuardSignatures(msg.sig, abi.encode(prevGuard, oldGuard, newGuard), signatures); - guards[newGuard] = guards[oldGuard]; - guards[prevGuard] = newGuard; - guards[oldGuard] = address(0); - emit RemovedGuard(oldGuard); - emit AddedGuard(newGuard); - } - - /** - * @dev Allows to update the number of required confirmations by guards. - * This can only be done via multi-sig. - * @notice Changes the threshold of the registry to `_threshold`. - * @param _threshold New threshold. - * @param signatures The signatures of the guards which to update the `threshold` . - */ - function changeThreshold(uint256 _threshold, bytes[] memory signatures) public { - verifyGuardSignatures(msg.sig, abi.encode(_threshold), signatures); - _changeThreshold(_threshold); - } - - function _changeThreshold(uint256 _threshold) internal { - // Validate that threshold is smaller than number of owners. - require(_threshold <= guardCount, "Guard: Threshold cannot exceed guard count"); - // There has to be at least one guard. - require(_threshold >= 1, "Guard: Threshold needs to be greater than 0"); - threshold = _threshold; - emit ChangedThreshold(threshold); - } - - function getThreshold() public view returns (uint256) { - return threshold; - } - - function isGuard(address guard) public view returns (bool) { - return guard != SENTINEL_GUARDS && guards[guard] != address(0); - } - - /** - * @dev Returns array of guards. - * @return Array of guards. - */ - function getGuards() public view returns (address[] memory) { - address[] memory array = new address[](guardCount); - - // populate return array - uint256 index = 0; - address currentGuard = guards[SENTINEL_GUARDS]; - while (currentGuard != SENTINEL_GUARDS) { - array[index] = currentGuard; - currentGuard = guards[currentGuard]; - index++; - } - return array; - } - - function verifyGuardSignatures( - bytes4 methodID, - bytes memory params, - bytes[] memory signatures - ) internal { - bytes32 structHash = - keccak256( - abi.encode( - methodID, - params, - nonce - ) - ); - checkGuardSignatures(structHash, signatures); - nonce++; - } - - function verifyGuardSignaturesWithoutNonce( - bytes4 methodID, - bytes memory params, - bytes[] memory signatures - ) view internal { - bytes32 structHash = - keccak256( - abi.encode( - methodID, - params - ) - ); - checkGuardSignatures(structHash, signatures); - } - - /** - * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise. - * @param structHash The struct Hash of the data (could be either a message/commitment hash). - * @param signatures Signature data that should be verified. only ECDSA signature. - * Signers need to be sorted in ascending order - */ - function checkGuardSignatures( - bytes32 structHash, - bytes[] memory signatures - ) public view { - // Load threshold to avoid multiple storage loads - uint256 _threshold = threshold; - // Check that a threshold is set - require(_threshold > 0, "Guard: Threshold needs to be defined"); - bytes32 dataHash = encodeDataHash(structHash); - checkNSignatures(dataHash, signatures, _threshold); - } - - /** - * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise. - * @param dataHash Hash of the data (could be either a message hash or transaction hash). - * @param signatures Signature data that should be verified. only ECDSA signature. - * Signers need to be sorted in ascending order - * @param requiredSignatures Amount of required valid signatures. - */ - function checkNSignatures( - bytes32 dataHash, - bytes[] memory signatures, - uint256 requiredSignatures - ) public view { - // Check that the provided signature data is not too short - require(signatures.length >= requiredSignatures, "GS020"); - // There cannot be an owner with address 0. - address lastGuard = address(0); - address currentGuard; - for (uint256 i = 0; i < requiredSignatures; i++) { - currentGuard = ECDSA.recover(dataHash, signatures[i]); - require(currentGuard > lastGuard && guards[currentGuard] != address(0) && currentGuard != SENTINEL_GUARDS, "Guard: Invalid guard provided"); - lastGuard = currentGuard; - } - } - - /** - * @dev Returns the chain id used by this contract. - */ - function getChainId() public view returns (uint256) { - uint256 id; - // solhint-disable-next-line no-inline-assembly - assembly { - id := chainid() - } - return id; - } - - function domainSeparator() public view returns (bytes32) { - return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), address(this))); - } - - function encodeDataHash(bytes32 structHash) public view returns (bytes32) { - return keccak256(abi.encodePacked(hex"1901", domainSeparator(), structHash)); - } -} - -// 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 @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) - - -// CAUTION -// This version of SafeMath should only be used with Solidity 0.8 or later, -// because it relies on the compiler's built in overflow checks. - -/** - * @dev Wrappers over Solidity's arithmetic operations. - * - * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler - * now has built in overflow checking. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - return a + b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - return a * b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b <= a, errorMessage); - return a - b; - } - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a / b; - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a % b; - } - } -} - -// File contracts/mapping-token/v2/Guard.sol -// License-Identifier: Apache-2.0 - - - - - - -contract Guard is GuardRegistry, Pausable { - using SafeMath for uint256; - - mapping(uint256 => bytes32) depositors; - - uint256 public maxUnclaimableTime; - address public depositor; - address public operator; - - event TokenDeposit(uint256 id, address token, address recipient, uint256 amount); - event TokenClaimed(uint256 id); - - constructor(address[] memory _guards, uint256 _threshold, uint256 _maxUnclaimableTime, address _depositor) { - maxUnclaimableTime = _maxUnclaimableTime; - depositor = _depositor; - operator = msg.sender; - initialize(_guards, _threshold); - } - - modifier onlyDepositor() { - require(msg.sender == depositor, "Guard: Invalid depositor"); - _; - } - - modifier onlyOperator() { - require(msg.sender == operator, "Guard: Invalid operator"); - _; - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } - - function setOperator(address newOperator, bytes[] memory signatures) external { - verifyGuardSignatures(msg.sig, abi.encode(newOperator), signatures); - operator = newOperator; - } - - function setMaxUnclaimableTime(uint256 _maxUnclaimableTime) external onlyOperator { - maxUnclaimableTime = _maxUnclaimableTime; - } - - /** - * @dev deposit token to guard, waiting to claim, only allowed depositor - * @param id the id of the operation, should be siged later by guards - * @param token the erc20 token address - * @param recipient the recipient of the token - * @param amount the amount of the token - */ - function deposit( - uint256 id, - address token, - address recipient, - uint256 amount - ) public onlyDepositor whenNotPaused { - depositors[id] = hash(abi.encodePacked(block.timestamp, token, recipient, amount)); - emit TokenDeposit(id, token, recipient, amount); - } - - function claimById( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bool isNative - ) internal { - require(hash(abi.encodePacked(timestamp, token, recipient, amount)) == depositors[id], "Guard: Invalid id to claim"); - require(amount > 0, "Guard: Invalid amount to claim"); - if (isNative) { - require(IERC20(token).transferFrom(depositor, address(this), amount), "Guard: claim native token failed"); - 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); - } else { - require(IERC20(token).transferFrom(depositor, recipient, amount), "Guard: claim token failed"); - } - delete depositors[id]; - emit TokenClaimed(id); - } - - /** - * @dev claim the tokens in the contract saved by deposit, this acquire signatures from guards - * @param id the id to be claimed - * @param signatures the signatures of the guards which to claim tokens. - */ - function claim( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bytes[] memory signatures - ) public { - verifyGuardSignaturesWithoutNonce(msg.sig, abi.encode(id, timestamp, token, recipient, amount), signatures); - claimById(id, timestamp, token, recipient, amount, false); - } - - /** - * @dev claimNative the tokens in the contract saved by deposit, this acquire signatures from guards - * @param id the id to be claimed - * @param signatures the signatures of the guards which to claim tokens. - */ - function claimNative( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bytes[] memory signatures - ) public { - verifyGuardSignaturesWithoutNonce(msg.sig, abi.encode(id, timestamp, token, recipient, amount), signatures); - claimById(id, timestamp, token, recipient, amount, true); - } - - /** - * @dev claim the tokens without signatures, this only allowed when timeout - * @param id the id to be claimed - */ - function claimByTimeout( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bool isNative - ) public whenNotPaused { - require(timestamp < block.timestamp && block.timestamp - timestamp > maxUnclaimableTime, "Guard: claim at invalid time"); - claimById(id, timestamp, token, recipient, amount, isNative); - } - - function hash(bytes memory value) public pure returns (bytes32) { - return sha256(value); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/ProxyAdmin.sol b/helix-contract/flatten/sub2eth/ProxyAdmin.sol deleted file mode 100644 index f56cfa15..00000000 --- a/helix-contract/flatten/sub2eth/ProxyAdmin.sol +++ /dev/null @@ -1,985 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 9/27/2022 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/proxy/Proxy.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) - - -/** - * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM - * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to - * be specified by overriding the virtual {_implementation} function. - * - * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a - * different contract through the {_delegate} function. - * - * The success and return data of the delegated call will be returned back to the caller of the proxy. - */ -abstract contract Proxy { - /** - * @dev Delegates the current call to `implementation`. - * - * This function does not return to its internal call site, it will return directly to the external caller. - */ - function _delegate(address implementation) internal virtual { - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize()) - - // Call the implementation. - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } - - /** - * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function - * and {_fallback} should delegate. - */ - function _implementation() internal view virtual returns (address); - - /** - * @dev Delegates the current call to the address returned by `_implementation()`. - * - * This function does not return to its internal call site, it will return directly to the external caller. - */ - function _fallback() internal virtual { - _beforeFallback(); - _delegate(_implementation()); - } - - /** - * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other - * function in the contract matches the call data. - */ - fallback() external payable virtual { - _fallback(); - } - - /** - * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data - * is empty. - */ - receive() external payable virtual { - _fallback(); - } - - /** - * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` - * call, or as part of the Solidity `fallback` or `receive` functions. - * - * If overridden should call `super._beforeFallback()`. - */ - function _beforeFallback() internal virtual {} -} - -// File @zeppelin-solidity/contracts/proxy/beacon/IBeacon.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) - - -/** - * @dev This is the interface that {BeaconProxy} expects of its beacon. - */ -interface IBeacon { - /** - * @dev Must return an address that can be used as a delegate call target. - * - * {BeaconProxy} will check that this address is a contract. - */ - function implementation() external view returns (address); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/interfaces/draft-IERC1822.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) - - -/** - * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified - * proxy whose upgrades are fully controlled by the current implementation. - */ -interface IERC1822Proxiable { - /** - * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation - * address. - * - * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks - * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this - * function revert if invoked through a proxy. - */ - function proxiableUUID() external view returns (bytes32); -} - -// File @zeppelin-solidity/contracts/utils/StorageSlot.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) - - -/** - * @dev Library for reading and writing primitive types to specific storage slots. - * - * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. - * This library helps with reading and writing to such slots without the need for inline assembly. - * - * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. - * - * Example usage to set ERC1967 implementation slot: - * ``` - * contract ERC1967 { - * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - * - * function _getImplementation() internal view returns (address) { - * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; - * } - * - * function _setImplementation(address newImplementation) internal { - * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); - * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; - * } - * } - * ``` - * - * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ - */ -library StorageSlot { - struct AddressSlot { - address value; - } - - struct BooleanSlot { - bool value; - } - - struct Bytes32Slot { - bytes32 value; - } - - struct Uint256Slot { - uint256 value; - } - - /** - * @dev Returns an `AddressSlot` with member `value` located at `slot`. - */ - function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `BooleanSlot` with member `value` located at `slot`. - */ - function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. - */ - function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Uint256Slot` with member `value` located at `slot`. - */ - function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } -} - -// File @zeppelin-solidity/contracts/proxy/ERC1967/ERC1967Upgrade.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) - - - - - -/** - * @dev This abstract contract provides getters and event emitting update functions for - * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. - * - * _Available since v4.1._ - * - * @custom:oz-upgrades-unsafe-allow delegatecall - */ -abstract contract ERC1967Upgrade { - // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 - bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; - - /** - * @dev Storage slot with the address of the current implementation. - * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is - * validated in the constructor. - */ - bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - - /** - * @dev Emitted when the implementation is upgraded. - */ - event Upgraded(address indexed implementation); - - /** - * @dev Returns the current implementation address. - */ - function _getImplementation() internal view returns (address) { - return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; - } - - /** - * @dev Stores a new address in the EIP1967 implementation slot. - */ - function _setImplementation(address newImplementation) private { - require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); - StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; - } - - /** - * @dev Perform implementation upgrade - * - * Emits an {Upgraded} event. - */ - function _upgradeTo(address newImplementation) internal { - _setImplementation(newImplementation); - emit Upgraded(newImplementation); - } - - /** - * @dev Perform implementation upgrade with additional setup call. - * - * Emits an {Upgraded} event. - */ - function _upgradeToAndCall( - address newImplementation, - bytes memory data, - bool forceCall - ) internal { - _upgradeTo(newImplementation); - if (data.length > 0 || forceCall) { - Address.functionDelegateCall(newImplementation, data); - } - } - - /** - * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. - * - * Emits an {Upgraded} event. - */ - function _upgradeToAndCallUUPS( - address newImplementation, - bytes memory data, - bool forceCall - ) internal { - // Upgrades from old implementations will perform a rollback test. This test requires the new - // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing - // this special case will break upgrade paths from old UUPS implementation to new ones. - if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { - _setImplementation(newImplementation); - } else { - try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { - require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); - } catch { - revert("ERC1967Upgrade: new implementation is not UUPS"); - } - _upgradeToAndCall(newImplementation, data, forceCall); - } - } - - /** - * @dev Storage slot with the admin of the contract. - * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is - * validated in the constructor. - */ - bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - - /** - * @dev Emitted when the admin account has changed. - */ - event AdminChanged(address previousAdmin, address newAdmin); - - /** - * @dev Returns the current admin. - */ - function _getAdmin() internal view returns (address) { - return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; - } - - /** - * @dev Stores a new address in the EIP1967 admin slot. - */ - function _setAdmin(address newAdmin) private { - require(newAdmin != address(0), "ERC1967: new admin is the zero address"); - StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; - } - - /** - * @dev Changes the admin of the proxy. - * - * Emits an {AdminChanged} event. - */ - function _changeAdmin(address newAdmin) internal { - emit AdminChanged(_getAdmin(), newAdmin); - _setAdmin(newAdmin); - } - - /** - * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. - * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. - */ - bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; - - /** - * @dev Emitted when the beacon is upgraded. - */ - event BeaconUpgraded(address indexed beacon); - - /** - * @dev Returns the current beacon. - */ - function _getBeacon() internal view returns (address) { - return StorageSlot.getAddressSlot(_BEACON_SLOT).value; - } - - /** - * @dev Stores a new beacon in the EIP1967 beacon slot. - */ - function _setBeacon(address newBeacon) private { - require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); - require( - Address.isContract(IBeacon(newBeacon).implementation()), - "ERC1967: beacon implementation is not a contract" - ); - StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; - } - - /** - * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does - * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). - * - * Emits a {BeaconUpgraded} event. - */ - function _upgradeBeaconToAndCall( - address newBeacon, - bytes memory data, - bool forceCall - ) internal { - _setBeacon(newBeacon); - emit BeaconUpgraded(newBeacon); - if (data.length > 0 || forceCall) { - Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); - } - } -} - -// File @zeppelin-solidity/contracts/proxy/ERC1967/ERC1967Proxy.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) - - - -/** - * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an - * implementation address that can be changed. This address is stored in storage in the location specified by - * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the - * implementation behind the proxy. - */ -contract ERC1967Proxy is Proxy, ERC1967Upgrade { - /** - * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. - * - * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded - * function call, and allows initializing the storage of the proxy like a Solidity constructor. - */ - constructor(address _logic, bytes memory _data) payable { - _upgradeToAndCall(_logic, _data, false); - } - - /** - * @dev Returns the current implementation address. - */ - function _implementation() internal view virtual override returns (address impl) { - return ERC1967Upgrade._getImplementation(); - } -} - -// File @zeppelin-solidity/contracts/proxy/transparent/TransparentUpgradeableProxy.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol) - - -/** - * @dev This contract implements a proxy that is upgradeable by an admin. - * - * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector - * clashing], which can potentially be used in an attack, this contract uses the - * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two - * things that go hand in hand: - * - * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if - * that call matches one of the admin functions exposed by the proxy itself. - * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the - * implementation. If the admin tries to call a function on the implementation it will fail with an error that says - * "admin cannot fallback to proxy target". - * - * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing - * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due - * to sudden errors when trying to call a function from the proxy implementation. - * - * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, - * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. - */ -contract TransparentUpgradeableProxy is ERC1967Proxy { - /** - * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and - * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. - */ - constructor( - address _logic, - address admin_, - bytes memory _data - ) payable ERC1967Proxy(_logic, _data) { - _changeAdmin(admin_); - } - - /** - * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. - */ - modifier ifAdmin() { - if (msg.sender == _getAdmin()) { - _; - } else { - _fallback(); - } - } - - /** - * @dev Returns the current admin. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. - * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. - * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` - */ - function admin() external ifAdmin returns (address admin_) { - admin_ = _getAdmin(); - } - - /** - * @dev Returns the current implementation. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. - * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. - * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` - */ - function implementation() external ifAdmin returns (address implementation_) { - implementation_ = _implementation(); - } - - /** - * @dev Changes the admin of the proxy. - * - * Emits an {AdminChanged} event. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. - */ - function changeAdmin(address newAdmin) external virtual ifAdmin { - _changeAdmin(newAdmin); - } - - /** - * @dev Upgrade the implementation of the proxy. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. - */ - function upgradeTo(address newImplementation) external ifAdmin { - _upgradeToAndCall(newImplementation, bytes(""), false); - } - - /** - * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified - * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the - * proxied contract. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. - */ - function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { - _upgradeToAndCall(newImplementation, data, true); - } - - /** - * @dev Returns the current admin. - */ - function _admin() internal view virtual returns (address) { - return _getAdmin(); - } - - /** - * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. - */ - function _beforeFallback() internal virtual override { - require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); - super._beforeFallback(); - } -} - -// 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/access/Ownable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - -// File @zeppelin-solidity/contracts/proxy/transparent/ProxyAdmin.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol) - - - -/** - * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an - * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. - */ -contract ProxyAdmin is Ownable { - /** - * @dev Returns the current implementation of `proxy`. - * - * Requirements: - * - * - This contract must be the admin of `proxy`. - */ - function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) { - // We need to manually run the static call since the getter cannot be flagged as view - // bytes4(keccak256("implementation()")) == 0x5c60da1b - (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); - require(success); - return abi.decode(returndata, (address)); - } - - /** - * @dev Returns the current admin of `proxy`. - * - * Requirements: - * - * - This contract must be the admin of `proxy`. - */ - function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) { - // We need to manually run the static call since the getter cannot be flagged as view - // bytes4(keccak256("admin()")) == 0xf851a440 - (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); - require(success); - return abi.decode(returndata, (address)); - } - - /** - * @dev Changes the admin of `proxy` to `newAdmin`. - * - * Requirements: - * - * - This contract must be the current admin of `proxy`. - */ - function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner { - proxy.changeAdmin(newAdmin); - } - - /** - * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. - * - * Requirements: - * - * - This contract must be the admin of `proxy`. - */ - function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner { - proxy.upgradeTo(implementation); - } - - /** - * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See - * {TransparentUpgradeableProxy-upgradeToAndCall}. - * - * Requirements: - * - * - This contract must be the admin of `proxy`. - */ - function upgradeAndCall( - TransparentUpgradeableProxy proxy, - address implementation, - bytes memory data - ) public payable virtual onlyOwner { - proxy.upgradeToAndCall{value: msg.value}(implementation, data); - } -} - -// File contracts/mapping-token/deprecated/admin.sol -// License-Identifier: MIT \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/TransparentUpgradeableProxy.sol b/helix-contract/flatten/sub2eth/TransparentUpgradeableProxy.sol deleted file mode 100644 index f211ef22..00000000 --- a/helix-contract/flatten/sub2eth/TransparentUpgradeableProxy.sol +++ /dev/null @@ -1,798 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 9/27/2022 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/proxy/Proxy.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) - - -/** - * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM - * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to - * be specified by overriding the virtual {_implementation} function. - * - * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a - * different contract through the {_delegate} function. - * - * The success and return data of the delegated call will be returned back to the caller of the proxy. - */ -abstract contract Proxy { - /** - * @dev Delegates the current call to `implementation`. - * - * This function does not return to its internal call site, it will return directly to the external caller. - */ - function _delegate(address implementation) internal virtual { - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize()) - - // Call the implementation. - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } - - /** - * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function - * and {_fallback} should delegate. - */ - function _implementation() internal view virtual returns (address); - - /** - * @dev Delegates the current call to the address returned by `_implementation()`. - * - * This function does not return to its internal call site, it will return directly to the external caller. - */ - function _fallback() internal virtual { - _beforeFallback(); - _delegate(_implementation()); - } - - /** - * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other - * function in the contract matches the call data. - */ - fallback() external payable virtual { - _fallback(); - } - - /** - * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data - * is empty. - */ - receive() external payable virtual { - _fallback(); - } - - /** - * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` - * call, or as part of the Solidity `fallback` or `receive` functions. - * - * If overridden should call `super._beforeFallback()`. - */ - function _beforeFallback() internal virtual {} -} - -// File @zeppelin-solidity/contracts/interfaces/draft-IERC1822.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) - - -/** - * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified - * proxy whose upgrades are fully controlled by the current implementation. - */ -interface IERC1822Proxiable { - /** - * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation - * address. - * - * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks - * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this - * function revert if invoked through a proxy. - */ - function proxiableUUID() external view returns (bytes32); -} - -// File @zeppelin-solidity/contracts/proxy/beacon/IBeacon.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) - - -/** - * @dev This is the interface that {BeaconProxy} expects of its beacon. - */ -interface IBeacon { - /** - * @dev Must return an address that can be used as a delegate call target. - * - * {BeaconProxy} will check that this address is a contract. - */ - function implementation() external view returns (address); -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/utils/StorageSlot.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) - - -/** - * @dev Library for reading and writing primitive types to specific storage slots. - * - * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. - * This library helps with reading and writing to such slots without the need for inline assembly. - * - * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. - * - * Example usage to set ERC1967 implementation slot: - * ``` - * contract ERC1967 { - * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - * - * function _getImplementation() internal view returns (address) { - * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; - * } - * - * function _setImplementation(address newImplementation) internal { - * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); - * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; - * } - * } - * ``` - * - * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ - */ -library StorageSlot { - struct AddressSlot { - address value; - } - - struct BooleanSlot { - bool value; - } - - struct Bytes32Slot { - bytes32 value; - } - - struct Uint256Slot { - uint256 value; - } - - /** - * @dev Returns an `AddressSlot` with member `value` located at `slot`. - */ - function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `BooleanSlot` with member `value` located at `slot`. - */ - function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. - */ - function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Uint256Slot` with member `value` located at `slot`. - */ - function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } -} - -// File @zeppelin-solidity/contracts/proxy/ERC1967/ERC1967Upgrade.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) - - - - - -/** - * @dev This abstract contract provides getters and event emitting update functions for - * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. - * - * _Available since v4.1._ - * - * @custom:oz-upgrades-unsafe-allow delegatecall - */ -abstract contract ERC1967Upgrade { - // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 - bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; - - /** - * @dev Storage slot with the address of the current implementation. - * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is - * validated in the constructor. - */ - bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - - /** - * @dev Emitted when the implementation is upgraded. - */ - event Upgraded(address indexed implementation); - - /** - * @dev Returns the current implementation address. - */ - function _getImplementation() internal view returns (address) { - return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; - } - - /** - * @dev Stores a new address in the EIP1967 implementation slot. - */ - function _setImplementation(address newImplementation) private { - require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); - StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; - } - - /** - * @dev Perform implementation upgrade - * - * Emits an {Upgraded} event. - */ - function _upgradeTo(address newImplementation) internal { - _setImplementation(newImplementation); - emit Upgraded(newImplementation); - } - - /** - * @dev Perform implementation upgrade with additional setup call. - * - * Emits an {Upgraded} event. - */ - function _upgradeToAndCall( - address newImplementation, - bytes memory data, - bool forceCall - ) internal { - _upgradeTo(newImplementation); - if (data.length > 0 || forceCall) { - Address.functionDelegateCall(newImplementation, data); - } - } - - /** - * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. - * - * Emits an {Upgraded} event. - */ - function _upgradeToAndCallUUPS( - address newImplementation, - bytes memory data, - bool forceCall - ) internal { - // Upgrades from old implementations will perform a rollback test. This test requires the new - // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing - // this special case will break upgrade paths from old UUPS implementation to new ones. - if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { - _setImplementation(newImplementation); - } else { - try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { - require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); - } catch { - revert("ERC1967Upgrade: new implementation is not UUPS"); - } - _upgradeToAndCall(newImplementation, data, forceCall); - } - } - - /** - * @dev Storage slot with the admin of the contract. - * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is - * validated in the constructor. - */ - bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - - /** - * @dev Emitted when the admin account has changed. - */ - event AdminChanged(address previousAdmin, address newAdmin); - - /** - * @dev Returns the current admin. - */ - function _getAdmin() internal view returns (address) { - return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; - } - - /** - * @dev Stores a new address in the EIP1967 admin slot. - */ - function _setAdmin(address newAdmin) private { - require(newAdmin != address(0), "ERC1967: new admin is the zero address"); - StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; - } - - /** - * @dev Changes the admin of the proxy. - * - * Emits an {AdminChanged} event. - */ - function _changeAdmin(address newAdmin) internal { - emit AdminChanged(_getAdmin(), newAdmin); - _setAdmin(newAdmin); - } - - /** - * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. - * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. - */ - bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; - - /** - * @dev Emitted when the beacon is upgraded. - */ - event BeaconUpgraded(address indexed beacon); - - /** - * @dev Returns the current beacon. - */ - function _getBeacon() internal view returns (address) { - return StorageSlot.getAddressSlot(_BEACON_SLOT).value; - } - - /** - * @dev Stores a new beacon in the EIP1967 beacon slot. - */ - function _setBeacon(address newBeacon) private { - require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); - require( - Address.isContract(IBeacon(newBeacon).implementation()), - "ERC1967: beacon implementation is not a contract" - ); - StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; - } - - /** - * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does - * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). - * - * Emits a {BeaconUpgraded} event. - */ - function _upgradeBeaconToAndCall( - address newBeacon, - bytes memory data, - bool forceCall - ) internal { - _setBeacon(newBeacon); - emit BeaconUpgraded(newBeacon); - if (data.length > 0 || forceCall) { - Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); - } - } -} - -// File @zeppelin-solidity/contracts/proxy/ERC1967/ERC1967Proxy.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) - - - -/** - * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an - * implementation address that can be changed. This address is stored in storage in the location specified by - * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the - * implementation behind the proxy. - */ -contract ERC1967Proxy is Proxy, ERC1967Upgrade { - /** - * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. - * - * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded - * function call, and allows initializing the storage of the proxy like a Solidity constructor. - */ - constructor(address _logic, bytes memory _data) payable { - _upgradeToAndCall(_logic, _data, false); - } - - /** - * @dev Returns the current implementation address. - */ - function _implementation() internal view virtual override returns (address impl) { - return ERC1967Upgrade._getImplementation(); - } -} - -// File @zeppelin-solidity/contracts/proxy/transparent/TransparentUpgradeableProxy.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol) - - -/** - * @dev This contract implements a proxy that is upgradeable by an admin. - * - * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector - * clashing], which can potentially be used in an attack, this contract uses the - * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two - * things that go hand in hand: - * - * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if - * that call matches one of the admin functions exposed by the proxy itself. - * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the - * implementation. If the admin tries to call a function on the implementation it will fail with an error that says - * "admin cannot fallback to proxy target". - * - * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing - * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due - * to sudden errors when trying to call a function from the proxy implementation. - * - * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, - * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. - */ -contract TransparentUpgradeableProxy is ERC1967Proxy { - /** - * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and - * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. - */ - constructor( - address _logic, - address admin_, - bytes memory _data - ) payable ERC1967Proxy(_logic, _data) { - _changeAdmin(admin_); - } - - /** - * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. - */ - modifier ifAdmin() { - if (msg.sender == _getAdmin()) { - _; - } else { - _fallback(); - } - } - - /** - * @dev Returns the current admin. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. - * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. - * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` - */ - function admin() external ifAdmin returns (address admin_) { - admin_ = _getAdmin(); - } - - /** - * @dev Returns the current implementation. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. - * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. - * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` - */ - function implementation() external ifAdmin returns (address implementation_) { - implementation_ = _implementation(); - } - - /** - * @dev Changes the admin of the proxy. - * - * Emits an {AdminChanged} event. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. - */ - function changeAdmin(address newAdmin) external virtual ifAdmin { - _changeAdmin(newAdmin); - } - - /** - * @dev Upgrade the implementation of the proxy. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. - */ - function upgradeTo(address newImplementation) external ifAdmin { - _upgradeToAndCall(newImplementation, bytes(""), false); - } - - /** - * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified - * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the - * proxied contract. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. - */ - function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { - _upgradeToAndCall(newImplementation, data, true); - } - - /** - * @dev Returns the current admin. - */ - function _admin() internal view virtual returns (address) { - return _getAdmin(); - } - - /** - * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. - */ - function _beforeFallback() internal virtual override { - require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); - super._beforeFallback(); - } -} - -// File contracts/mapping-token/deprecated/proxy.sol -// License-Identifier: MIT \ No newline at end of file diff --git a/helix-contract/flatten/sub2eth/WToken.sol b/helix-contract/flatten/sub2eth/WToken.sol deleted file mode 100644 index d061b8dc..00000000 --- a/helix-contract/flatten/sub2eth/WToken.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 5/12/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/mapping-token/v2/erc20-mapping-protocol/WToken.sol -// License-Identifier: MIT - - -contract WToken { - string public name; - string public symbol; - uint8 public decimals; - - event Approval(address indexed src, address indexed guy, uint wad); - event Transfer(address indexed src, address indexed dst, uint wad); - event Deposit(address indexed dst, uint wad); - event Withdrawal(address indexed src, uint wad); - - mapping (address => uint) public balanceOf; - mapping (address => mapping (address => uint)) public allowance; - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - } - - receive() external payable { - deposit(); - } - - function deposit() public payable { - balanceOf[msg.sender] += msg.value; - emit Deposit(msg.sender, msg.value); - } - function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - payable(msg.sender).transfer(wad); - emit Withdrawal(msg.sender, wad); - } - - function totalSupply() public view returns (uint) { - return address(this).balance; - } - - function approve(address guy, uint wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - emit Approval(msg.sender, guy, wad); - return true; - } - - function transfer(address dst, uint wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint wad) - public - returns (bool) - { - require(balanceOf[src] >= wad); - - if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - emit Transfer(src, dst, wad); - - return true; - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2sub/DarwiniaSub2SubMessageEndpoint.sol b/helix-contract/flatten/sub2sub/DarwiniaSub2SubMessageEndpoint.sol deleted file mode 100644 index be18327c..00000000 --- a/helix-contract/flatten/sub2sub/DarwiniaSub2SubMessageEndpoint.sol +++ /dev/null @@ -1,4547 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 4/28/2023 - **/ - -pragma solidity ^0.8.10; - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// 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/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/AccessController.sol -// License-Identifier: MIT - - -contract AccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - bytes32 public constant CALLER_ROLE = keccak256("CALLER_ROLE"); - bytes32 public constant CALLEE_ROLE = keccak256("CALLEE_ROLE"); - - // access controller - // admin is helix Dao - modifier onlyAdmin() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "AccessController:Bad admin role"); - _; - } - - // operator - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "AccessController:Bad operator role"); - _; - } - - modifier onlyCaller() { - require(hasRole(CALLER_ROLE, msg.sender), "AccessController:Bad caller role"); - _; - } - - modifier onlyCallee() { - require(hasRole(CALLEE_ROLE, msg.sender), "AccessController:Bad callee role"); - _; - } - - function _initialize(address admin) internal { - _setRoleAdmin(CALLER_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(CALLEE_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, admin); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @darwinia/contracts-utils/contracts/Blake2b.sol@v1.0.4 -/* - * Blake2b library in Solidity using EIP-152 - * - * Copyright (C) 2019 Alex Beregszaszi - * - * License: Apache 2.0 - */ - -// License-Identifier: MIT - -pragma experimental ABIEncoderV2; - -library Blake2b { - struct Instance { - // This is a bit misleadingly called state as it not only includes the Blake2 state, - // but every field needed for the "blake2 f function precompile". - // - // This is a tightly packed buffer of: - // - rounds: 32-bit BE - // - h: 8 x 64-bit LE - // - m: 16 x 64-bit LE - // - t: 2 x 64-bit LE - // - f: 8-bit - bytes state; - // Expected output hash length. (Used in `finalize`.) - uint out_len; - // Data passed to "function F". - // NOTE: this is limited to 24 bits. - uint input_counter; - } - - // Initialise the state with a given `key` and required `out_len` hash length. - function init(bytes memory key, uint out_len) - internal - view - returns (Instance memory instance) - { - // Safety check that the precompile exists. - // TODO: remove this? - // assembly { - // if eq(extcodehash(0x09), 0) { revert(0, 0) } - //} - - reset(instance, key, out_len); - } - - // Initialise the state with a given `key` and required `out_len` hash length. - function reset(Instance memory instance, bytes memory key, uint out_len) - internal - view - { - instance.out_len = out_len; - instance.input_counter = 0; - - // This is entire state transmitted to the precompile. - // It is byteswapped for the encoding requirements, additionally - // the IV has the initial parameter block 0 XOR constant applied, but - // not the key and output length. - instance.state = hex"0000000c08c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - bytes memory state = instance.state; - - // Update parameter block 0 with key length and output length. - uint key_len = key.length; - assembly { - let ptr := add(state, 36) - let tmp := mload(ptr) - let p0 := or(shl(240, key_len), shl(248, out_len)) - tmp := xor(tmp, p0) - mstore(ptr, tmp) - } - - // TODO: support salt and personalization - - if (key_len > 0) { - require(key_len == 64); - // FIXME: the key must be zero padded - assert(key.length == 128); - update(instance, key, key_len); - } - } - - // This calls the blake2 precompile ("function F of the spec"). - // It expects the state was updated with the next block. Upon returning the state will be updated, - // but the supplied block data will not be cleared. - function call_function_f(Instance memory instance) - private - view - { - bytes memory state = instance.state; - assembly { - let state_ptr := add(state, 32) - if iszero(staticcall(not(0), 0x09, state_ptr, 0xd5, add(state_ptr, 4), 0x40)) { - revert(0, 0) - } - } - } - - // This function will split blocks correctly and repeatedly call the precompile. - // NOTE: this is dumb right now and expects `data` to be 128 bytes long and padded with zeroes, - // hence the real length is indicated with `data_len` - function update_loop(Instance memory instance, bytes memory data, uint data_len, bool last_block) - private - view - { - bytes memory state = instance.state; - uint input_counter = instance.input_counter; - - // This is the memory location where the "data block" starts for the precompile. - uint state_ptr; - assembly { - // The `rounds` field is 4 bytes long and the `h` field is 64-bytes long. - // Also adjust for the size of the bytes type. - state_ptr := add(state, 100) - } - - // This is the memory location where the input data resides. - uint data_ptr; - assembly { - data_ptr := add(data, 32) - } - - uint len = data.length; - while (len > 0) { - if (len >= 128) { - assembly { - mstore(state_ptr, mload(data_ptr)) - data_ptr := add(data_ptr, 32) - - mstore(add(state_ptr, 32), mload(data_ptr)) - data_ptr := add(data_ptr, 32) - - mstore(add(state_ptr, 64), mload(data_ptr)) - data_ptr := add(data_ptr, 32) - - mstore(add(state_ptr, 96), mload(data_ptr)) - data_ptr := add(data_ptr, 32) - } - - len -= 128; - // FIXME: remove this once implemented proper padding - if (data_len < 128) { - input_counter += data_len; - } else { - data_len -= 128; - input_counter += 128; - } - } else { - // FIXME: implement support for smaller than 128 byte blocks - revert(); - } - - // Set length field (little-endian) for maximum of 24-bits. - assembly { - mstore8(add(state, 228), and(input_counter, 0xff)) - mstore8(add(state, 229), and(shr(8, input_counter), 0xff)) - mstore8(add(state, 230), and(shr(16, input_counter), 0xff)) - } - - // Set the last block indicator. - // Only if we've processed all input. - if (len == 0) { - assembly { - // Writing byte 212 here. - mstore8(add(state, 244), last_block) - } - } - - // Call the precompile - call_function_f(instance); - } - - instance.input_counter = input_counter; - } - - // Update the state with a non-final block. - // NOTE: the input must be complete blocks. - function update(Instance memory instance, bytes memory data, uint data_len) - internal - view - { - require((data.length % 128) == 0); - update_loop(instance, data, data_len, false); - } - - // Update the state with a final block and return the hash. - function finalize(Instance memory instance, bytes memory data) - internal - view - returns (bytes memory output) - { - // FIXME: support incomplete blocks (zero pad them) - uint input_length = data.length; - if (input_length == 0 || (input_length % 128) != 0) { - data = abi.encodePacked(data, new bytes(128 - (input_length % 128))); - } - assert((data.length % 128) == 0); - update_loop(instance, data, input_length, true); - - // FIXME: support other lengths - // assert(instance.out_len == 64); - - bytes memory state = instance.state; - output = new bytes(instance.out_len); - if (instance.out_len == 16) { - assembly { - mstore(add(output,16), mload(add(state, 20))) - mstore(output, 16) - } - } else if(instance.out_len == 32) { - assembly { - mstore(add(output, 32), mload(add(state, 36))) - } - } else { - assembly { - mstore(add(output, 32), mload(add(state, 36))) - mstore(add(output, 64), mload(add(state, 68))) - } - } - } - - function concat( - bytes memory _preBytes, - bytes memory _postBytes - ) - internal - pure - returns (bytes memory) - { - bytes memory tempBytes; - - assembly { - // Get a location of some free memory and store it in tempBytes as - // Solidity does for memory variables. - tempBytes := mload(0x40) - - // Store the length of the first bytes array at the beginning of - // the memory for tempBytes. - let length := mload(_preBytes) - mstore(tempBytes, length) - - // Maintain a memory counter for the current write location in the - // temp bytes array by adding the 32 bytes for the array length to - // the starting location. - let mc := add(tempBytes, 0x20) - // Stop copying when the memory counter reaches the length of the - // first bytes array. - let end := add(mc, length) - - for { - // Initialize a copy counter to the start of the _preBytes data, - // 32 bytes into its memory. - let cc := add(_preBytes, 0x20) - } lt(mc, end) { - // Increase both counters by 32 bytes each iteration. - mc := add(mc, 0x20) - cc := add(cc, 0x20) - } { - // Write the _preBytes data into the tempBytes memory 32 bytes - // at a time. - mstore(mc, mload(cc)) - } - - // Add the length of _postBytes to the current length of tempBytes - // and store it as the new length in the first 32 bytes of the - // tempBytes memory. - length := mload(_postBytes) - mstore(tempBytes, add(length, mload(tempBytes))) - - // Move the memory counter back from a multiple of 0x20 to the - // actual end of the _preBytes data. - mc := end - // Stop copying when the memory counter reaches the new combined - // length of the arrays. - end := add(mc, length) - - for { - let cc := add(_postBytes, 0x20) - } lt(mc, end) { - mc := add(mc, 0x20) - cc := add(cc, 0x20) - } { - mstore(mc, mload(cc)) - } - - // Update the free-memory pointer by padding our last write location - // to 32 bytes: add 31 bytes to the end of tempBytes to move to the - // next 32 byte block, then round down to the nearest multiple of - // 32. If the sum of the length of the two arrays is zero then add - // one before rounding down to leave a blank 32 bytes (the length block with 0). - mstore(0x40, and( - add(add(end, iszero(add(length, mload(_preBytes)))), 31), - not(31) // Round down to the nearest 32 bytes. - )) - } - - return tempBytes; - } - -} - -// File @darwinia/contracts-utils/contracts/Memory.sol@v1.0.4 -// License-Identifier: MIT - - -library Memory { - - uint internal constant WORD_SIZE = 32; - - // Compares the 'len' bytes starting at address 'addr' in memory with the 'len' - // bytes starting at 'addr2'. - // Returns 'true' if the bytes are the same, otherwise 'false'. - function equals(uint addr, uint addr2, uint len) internal pure returns (bool equal) { - assembly { - equal := eq(keccak256(addr, len), keccak256(addr2, len)) - } - } - - // Compares the 'len' bytes starting at address 'addr' in memory with the bytes stored in - // 'bts'. It is allowed to set 'len' to a lower value then 'bts.length', in which case only - // the first 'len' bytes will be compared. - // Requires that 'bts.length >= len' - - function equals(uint addr, uint len, bytes memory bts) internal pure returns (bool equal) { - require(bts.length >= len); - uint addr2; - assembly { - addr2 := add(bts, /*BYTES_HEADER_SIZE*/32) - } - return equals(addr, addr2, len); - } - // Returns a memory pointer to the data portion of the provided bytes array. - function dataPtr(bytes memory bts) internal pure returns (uint addr) { - assembly { - addr := add(bts, /*BYTES_HEADER_SIZE*/32) - } - } - - // Creates a 'bytes memory' variable from the memory address 'addr', with the - // length 'len'. The function will allocate new memory for the bytes array, and - // the 'len bytes starting at 'addr' will be copied into that new memory. - function toBytes(uint addr, uint len) internal pure returns (bytes memory bts) { - bts = new bytes(len); - uint btsptr; - assembly { - btsptr := add(bts, /*BYTES_HEADER_SIZE*/32) - } - copy(addr, btsptr, len); - } - - // Copies 'self' into a new 'bytes memory'. - // Returns the newly created 'bytes memory' - // The returned bytes will be of length '32'. - function toBytes(bytes32 self) internal pure returns (bytes memory bts) { - bts = new bytes(32); - assembly { - mstore(add(bts, /*BYTES_HEADER_SIZE*/32), self) - } - } - - // Copy 'len' bytes from memory address 'src', to address 'dest'. - // This function does not check the or destination, it only copies - // the bytes. - function copy(uint src, uint dest, uint len) internal pure { - // Copy word-length chunks while possible - for (; len >= WORD_SIZE; len -= WORD_SIZE) { - assembly { - mstore(dest, mload(src)) - } - dest += WORD_SIZE; - src += WORD_SIZE; - } - - // Copy remaining bytes - uint mask = len == 0 ? 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff : 256 ** (WORD_SIZE - len) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - } - - // This function does the same as 'dataPtr(bytes memory)', but will also return the - // length of the provided bytes array. - function fromBytes(bytes memory bts) internal pure returns (uint addr, uint len) { - len = bts.length; - assembly { - addr := add(bts, /*BYTES_HEADER_SIZE*/32) - } - } -} - -// File @darwinia/contracts-utils/contracts/Bytes.sol@v1.0.4 -// License-Identifier: MIT - - -library Bytes { - uint256 internal constant BYTES_HEADER_SIZE = 32; - - // Checks if two `bytes memory` variables are equal. This is done using hashing, - // which is much more gas efficient then comparing each byte individually. - // Equality means that: - // - 'self.length == other.length' - // - For 'n' in '[0, self.length)', 'self[n] == other[n]' - function equals(bytes memory self, bytes memory other) internal pure returns (bool equal) { - if (self.length != other.length) { - return false; - } - uint addr; - uint addr2; - assembly { - addr := add(self, /*BYTES_HEADER_SIZE*/32) - addr2 := add(other, /*BYTES_HEADER_SIZE*/32) - } - equal = Memory.equals(addr, addr2, self.length); - } - - // Copies a section of 'self' into a new array, starting at the provided 'startIndex'. - // Returns the new copy. - // Requires that 'startIndex <= self.length' - // The length of the substring is: 'self.length - startIndex' - function substr(bytes memory self, uint256 startIndex) - internal - pure - returns (bytes memory) - { - require(startIndex <= self.length); - uint256 len = self.length - startIndex; - uint256 addr = Memory.dataPtr(self); - return Memory.toBytes(addr + startIndex, len); - } - - // Copies 'len' bytes from 'self' into a new array, starting at the provided 'startIndex'. - // Returns the new copy. - // Requires that: - // - 'startIndex + len <= self.length' - // The length of the substring is: 'len' - function substr( - bytes memory self, - uint256 startIndex, - uint256 len - ) internal pure returns (bytes memory) { - require(startIndex + len <= self.length); - if (len == 0) { - return ""; - } - uint256 addr = Memory.dataPtr(self); - return Memory.toBytes(addr + startIndex, len); - } - - // Combines 'self' and 'other' into a single array. - // Returns the concatenated arrays: - // [self[0], self[1], ... , self[self.length - 1], other[0], other[1], ... , other[other.length - 1]] - // The length of the new array is 'self.length + other.length' - function concat(bytes memory self, bytes memory other) - internal - pure - returns (bytes memory) - { - bytes memory ret = new bytes(self.length + other.length); - uint256 src; - uint256 srcLen; - (src, srcLen) = Memory.fromBytes(self); - uint256 src2; - uint256 src2Len; - (src2, src2Len) = Memory.fromBytes(other); - uint256 dest; - (dest, ) = Memory.fromBytes(ret); - uint256 dest2 = dest + srcLen; - Memory.copy(src, dest, srcLen); - Memory.copy(src2, dest2, src2Len); - return ret; - } - - function toBytes32(bytes memory self) - internal - pure - returns (bytes32 out) - { - require(self.length >= 32, "Bytes:: toBytes32: data is to short."); - assembly { - out := mload(add(self, 32)) - } - } - - function toBytes16(bytes memory self, uint256 offset) - internal - pure - returns (bytes16 out) - { - for (uint i = 0; i < 16; i++) { - out |= bytes16(bytes1(self[offset + i]) & 0xFF) >> (i * 8); - } - } - - function toBytes8(bytes memory self, uint256 offset) - internal - pure - returns (bytes8 out) - { - for (uint i = 0; i < 8; i++) { - out |= bytes8(bytes1(self[offset + i]) & 0xFF) >> (i * 8); - } - } - - function toBytes4(bytes memory self, uint256 offset) - internal - pure - returns (bytes4) - { - bytes4 out; - - for (uint256 i = 0; i < 4; i++) { - out |= bytes4(self[offset + i] & 0xFF) >> (i * 8); - } - return out; - } - - function toBytes2(bytes memory self, uint256 offset) - internal - pure - returns (bytes2) - { - bytes2 out; - - for (uint256 i = 0; i < 2; i++) { - out |= bytes2(self[offset + i] & 0xFF) >> (i * 8); - } - return out; - } - - function removeLeadingZero(bytes memory data) internal pure returns (bytes memory) { - uint length = data.length; - - uint startIndex = 0; - for (uint i = 0; i < length; i++) { - if (data[i] != 0) { - startIndex = i; - break; - } - } - - return substr(data, startIndex); - } - - function removeEndingZero(bytes memory data) internal pure returns (bytes memory) { - uint length = data.length; - - uint endIndex = 0; - for (uint i = length - 1; i >= 0; i--) { - if (data[i] != 0) { - endIndex = i; - break; - } - } - - return substr(data, 0, endIndex + 1); - } - - function reverse(bytes memory inbytes) internal pure returns (bytes memory) { - uint inlength = inbytes.length; - bytes memory outbytes = new bytes(inlength); - - for (uint i = 0; i <= inlength - 1; i++) { - outbytes[i] = inbytes[inlength - i - 1]; - } - - return outbytes; - } -} - -// File @darwinia/contracts-utils/contracts/Hash.sol@v1.0.4 -// License-Identifier: MIT - - -// import "./Memory.sol"; - - -library Hash { - - using Blake2b for Blake2b.Instance; - - // function hash(bytes memory src) internal view returns (bytes memory des) { - // return Memory.toBytes(keccak256(src)); - // Blake2b.Instance memory instance = Blake2b.init(hex"", 32); - // return instance.finalize(src); - // } - - function blake2bHash(bytes memory src) internal view returns (bytes32 des) { - // return keccak256(src); - Blake2b.Instance memory instance = Blake2b.init(hex"", 32); - return abi.decode(instance.finalize(src), (bytes32)); - } - - // Blake2_128 - function blake2b128(bytes memory src) internal view returns (bytes16 des) { - Blake2b.Instance memory instance = Blake2b.init(hex"", 16); - return Bytes.toBytes16(instance.finalize(src), 0); - } - - // Blake2_128Concat - function blake2b128Concat(bytes memory src) internal view returns (bytes memory) { - Blake2b.Instance memory instance = Blake2b.init(hex"", 16); - return abi.encodePacked(instance.finalize(src), src); - } -} - -// File @darwinia/contracts-utils/contracts/ScaleCodec.sol@v1.0.4 -// License-Identifier: MIT - -library ScaleCodec { - // Decodes a SCALE encoded uint256 by converting bytes (big endian) to little endian format - function decodeUint256(bytes memory data) internal pure returns (uint256) { - uint256 number; - for (uint256 i = data.length; i > 0; i--) { - number = number + uint256(uint8(data[i - 1])) * (2**(8 * (i - 1))); - } - return number; - } - - function decodeUint128(bytes memory data) internal pure returns (uint128) { - require(data.length >= 16, "Bad data"); - bytes memory reversed = Bytes.reverse(data); - return uint128(Bytes.toBytes16(reversed, 0)); - } - - function decodeUint64(bytes memory data) internal pure returns (uint64) { - require(data.length >= 8, "Bad data"); - bytes memory reversed = Bytes.reverse(data); - return uint64(Bytes.toBytes8(reversed, 0)); - } - - // Decodes a SCALE encoded compact unsigned integer - function decodeUintCompact(bytes memory data) - internal - pure - returns (uint256 value, uint8 mode) - { - uint8 b = readByteAtIndex(data, 0); // read the first byte - mode = b & 3; // bitwise operation - - if (mode == 0) { - // [0, 63] - value = b >> 2; // right shift to remove mode bits - } else if (mode == 1) { - // [64, 16383] - uint8 bb = readByteAtIndex(data, 1); // read the second byte - uint64 r = bb; // convert to uint64 - r <<= 6; // multiply by * 2^6 - r += b >> 2; // right shift to remove mode bits - value = r; - } else if (mode == 2) { - // [16384, 1073741823] - uint8 b2 = readByteAtIndex(data, 1); // read the next 3 bytes - uint8 b3 = readByteAtIndex(data, 2); - uint8 b4 = readByteAtIndex(data, 3); - - uint32 x1 = uint32(b) | (uint32(b2) << 8); // convert to little endian - uint32 x2 = x1 | (uint32(b3) << 16); - uint32 x3 = x2 | (uint32(b4) << 24); - - x3 >>= 2; // remove the last 2 mode bits - value = uint256(x3); - } else if (mode == 3) { - // [1073741824, 4503599627370496] - uint8 l = b >> 2; // remove mode bits - require( - l > 32, - "Not supported: number cannot be greater than 32 bytes" - ); - } else { - revert("Code should be unreachable"); - } - } - - // The biggest compact supported uint is 2 ** 536 - 1. - // But the biggest value supported by this method is 2 ** 256 - 1(max of uint256) - function encodeUintCompact(uint256 v) internal pure returns (bytes memory) { - if ( v < 64 ) { - return abi.encodePacked(uint8(v << 2)); - } else if ( v < 2 ** 14 ) { - return abi.encodePacked(reverse16(uint16(((v << 2) + 1)))); - } else if ( v < 2 ** 30 ) { - return abi.encodePacked(reverse32(uint32(((v << 2) + 2)))); - } else { // 0b11, The upper six bits are the number of bytes following, plus four - bytes memory valueBytes = - Bytes.removeEndingZero(abi.encodePacked(reverse256(v))); - - uint length = valueBytes.length; - uint8 prefix = uint8(((length - 4) << 2) + 3); - - return abi.encodePacked(prefix, valueBytes); - } - } - - // Read a byte at a specific index and return it as type uint8 - function readByteAtIndex(bytes memory data, uint8 index) - internal - pure - returns (uint8) - { - return uint8(data[index]); - } - - // Sources: - // * https://ethereum.stackexchange.com/questions/15350/how-to-convert-an-bytes-to-address-in-solidity/50528 - // * https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel - - function reverse256(uint256 input) internal pure returns (uint256 v) { - v = input; - - // swap bytes - v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8) | - ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); - - // swap 2-byte long pairs - v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16) | - ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); - - // swap 4-byte long pairs - v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32) | - ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); - - // swap 8-byte long pairs - v = ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64) | - ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64); - - // swap 16-byte long pairs - v = (v >> 128) | (v << 128); - } - - function reverse128(uint128 input) internal pure returns (uint128 v) { - v = input; - - // swap bytes - v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00) >> 8) | - ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF) << 8); - - // swap 2-byte long pairs - v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000) >> 16) | - ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF) << 16); - - // swap 4-byte long pairs - v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000) >> 32) | - ((v & 0x00000000FFFFFFFF00000000FFFFFFFF) << 32); - - // swap 8-byte long pairs - v = (v >> 64) | (v << 64); - } - - function reverse64(uint64 input) internal pure returns (uint64 v) { - v = input; - - // swap bytes - v = ((v & 0xFF00FF00FF00FF00) >> 8) | - ((v & 0x00FF00FF00FF00FF) << 8); - - // swap 2-byte long pairs - v = ((v & 0xFFFF0000FFFF0000) >> 16) | - ((v & 0x0000FFFF0000FFFF) << 16); - - // swap 4-byte long pairs - v = (v >> 32) | (v << 32); - } - - function reverse32(uint32 input) internal pure returns (uint32 v) { - v = input; - - // swap bytes - v = ((v & 0xFF00FF00) >> 8) | - ((v & 0x00FF00FF) << 8); - - // swap 2-byte long pairs - v = (v >> 16) | (v << 16); - } - - function reverse16(uint16 input) internal pure returns (uint16 v) { - v = input; - - // swap bytes - v = (v >> 8) | (v << 8); - } - - function encode256(uint256 input) internal pure returns (bytes32) { - return bytes32(reverse256(input)); - } - - function encode128(uint128 input) internal pure returns (bytes16) { - return bytes16(reverse128(input)); - } - - function encode64(uint64 input) internal pure returns (bytes8) { - return bytes8(reverse64(input)); - } - - function encode32(uint32 input) internal pure returns (bytes4) { - return bytes4(reverse32(input)); - } - - function encode16(uint16 input) internal pure returns (bytes2) { - return bytes2(reverse16(input)); - } - - function encodeBytes(bytes memory input) internal pure returns (bytes memory) { - return abi.encodePacked( - encodeUintCompact(input.length), - input - ); - } - - -} - -// File @darwinia/contracts-utils/contracts/AccountId.sol@v1.0.4 -// License-Identifier: MIT - - -library AccountId { - bytes private constant prefixBytes = "dvm:"; - bytes private constant zeroBytes = hex"00000000000000"; - - function deriveSubstrateAddress(address addr) internal pure returns (bytes32) { - bytes memory body = abi.encodePacked( - prefixBytes, - zeroBytes, - addr - ); - uint8 checksum = checksumOf(body); - bytes memory result = abi.encodePacked(body, checksum); - return Bytes.toBytes32(result); - } - - function deriveEthereumAddress(bytes32 accountId) internal pure returns (address) { - return address(bytes20(accountId)); - } - - function deriveEthereumAddressFromDvm(bytes32 accountId) internal pure returns (address) { - return address(uint160(uint256(accountId) >> 8)); - } - - function checksumOf(bytes memory accountId) private pure returns (uint8) { - uint8 checksum = uint8(accountId[0]); - for (uint i = 1; i <= 30; i++) { - checksum = checksum ^ uint8(accountId[i]); - } - return checksum; - } -} - -// File @darwinia/contracts-periphery/contracts/s2s/interfaces/IStateStorage.sol@vv2.1.1-fix2 -// License-Identifier: MIT - - -interface IStateStorage { - function state_storage(bytes memory key) external view returns (bytes memory); -} - -// File hardhat/console.sol@v2.12.4 -// License-Identifier: MIT -pragma solidity >= 0.4.22 <0.9.0; - -library console { - address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); - - function _sendLogPayload(bytes memory payload) private view { - uint256 payloadLength = payload.length; - address consoleAddress = CONSOLE_ADDRESS; - assembly { - let payloadStart := add(payload, 32) - let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) - } - } - - function log() internal view { - _sendLogPayload(abi.encodeWithSignature("log()")); - } - - function logInt(int256 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); - } - - function logUint(uint256 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); - } - - function logString(string memory p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function logBool(bool p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function logAddress(address p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function logBytes(bytes memory p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); - } - - function logBytes1(bytes1 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); - } - - function logBytes2(bytes2 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); - } - - function logBytes3(bytes3 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); - } - - function logBytes4(bytes4 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); - } - - function logBytes5(bytes5 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); - } - - function logBytes6(bytes6 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); - } - - function logBytes7(bytes7 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); - } - - function logBytes8(bytes8 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); - } - - function logBytes9(bytes9 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); - } - - function logBytes10(bytes10 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); - } - - function logBytes11(bytes11 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); - } - - function logBytes12(bytes12 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); - } - - function logBytes13(bytes13 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); - } - - function logBytes14(bytes14 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); - } - - function logBytes15(bytes15 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); - } - - function logBytes16(bytes16 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); - } - - function logBytes17(bytes17 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); - } - - function logBytes18(bytes18 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); - } - - function logBytes19(bytes19 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); - } - - function logBytes20(bytes20 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); - } - - function logBytes21(bytes21 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); - } - - function logBytes22(bytes22 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); - } - - function logBytes23(bytes23 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); - } - - function logBytes24(bytes24 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); - } - - function logBytes25(bytes25 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); - } - - function logBytes26(bytes26 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); - } - - function logBytes27(bytes27 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); - } - - function logBytes28(bytes28 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); - } - - function logBytes29(bytes29 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); - } - - function logBytes30(bytes30 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); - } - - function logBytes31(bytes31 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); - } - - function logBytes32(bytes32 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); - } - - function log(uint256 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); - } - - function log(string memory p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function log(bool p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function log(address p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function log(uint256 p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); - } - - function log(uint256 p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); - } - - function log(uint256 p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); - } - - function log(uint256 p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); - } - - function log(string memory p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); - } - - function log(string memory p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); - } - - function log(string memory p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); - } - - function log(string memory p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); - } - - function log(bool p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); - } - - function log(bool p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); - } - - function log(bool p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); - } - - function log(bool p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); - } - - function log(address p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); - } - - function log(address p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); - } - - function log(address p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); - } - - function log(address p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); - } - - function log(uint256 p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); - } - - function log(string memory p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); - } - - function log(string memory p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); - } - - function log(string memory p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); - } - - function log(string memory p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); - } - - function log(bool p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); - } - - function log(bool p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); - } - - function log(bool p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); - } - - function log(bool p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); - } - - function log(bool p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); - } - - function log(bool p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); - } - - function log(bool p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); - } - - function log(bool p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); - } - - function log(address p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); - } - - function log(address p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); - } - - function log(address p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); - } - - function log(address p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); - } - - function log(address p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); - } - - function log(address p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); - } - - function log(address p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); - } - - function log(address p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); - } - - function log(address p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); - } - - function log(address p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); - } - - function log(address p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); - } - - function log(address p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); - } - -} - -// File @darwinia/contracts-periphery/contracts/s2s/types/CommonTypes.sol@vv2.1.1-fix2 -// License-Identifier: MIT - - - - -library CommonTypes { - struct EnumItemWithAccountId { - uint8 index; - address accountId; - } - - function encodeEnumItemWithAccountId( - EnumItemWithAccountId memory _item - ) internal pure returns (bytes memory) { - return abi.encodePacked(_item.index, _item.accountId); - } - - struct EnumItemWithNull { - uint8 index; - } - - function encodeEnumItemWithNull( - EnumItemWithNull memory _item - ) internal pure returns (bytes memory) { - return abi.encodePacked(_item.index); - } - - //////////////////////////////////// - // BitVecU8 - //////////////////////////////////// - function ceilDivide(uint a, uint b) internal pure returns (uint) { - if (a % b == 0) { - return a / b; - } else { - return a / b + 1; - } - } - - // bits: bit amount used, 1: true, 0: false - // bytesLength: bytes used by bits - // result: the bytes - struct BitVecU8 { - uint bits; - bytes result; - uint bytesLength; - } - - function decodeBitVecU8( - bytes memory _data - ) internal pure returns (BitVecU8 memory) { - (uint256 bits, uint8 mode) = ScaleCodec.decodeUintCompact(_data); - uint prefixLength = uint8(2 ** mode); - uint bytesLength = ceilDivide(bits, 8); - require( - _data.length >= prefixLength + bytesLength, - "The data is not enough to decode BitVecU8" - ); - return - BitVecU8( - bits, - Bytes.substr(_data, prefixLength, bytesLength), - prefixLength + bytesLength - ); - } - - //////////////////////////////////// - // Relayer - //////////////////////////////////// - struct Relayer { - bytes20 id; - uint128 collateral; - uint128 fee; - } - - // 52 bytes - function decodeRelayer( - bytes memory _data - ) internal pure returns (Relayer memory) { - require(_data.length >= 52, "The data is not enough to decode Relayer"); - - bytes20 id = bytes20(Bytes.substr(_data, 0, 20)); - - uint128 collateral = ScaleCodec.decodeUint128( - Bytes.substr(_data, 20, 16) - ); - - uint128 fee = ScaleCodec.decodeUint128(Bytes.substr(_data, 36, 16)); - - return Relayer(id, collateral, fee); - } - - function getLastRelayerFromVec( - bytes memory _data - ) internal pure returns (Relayer memory) { - // Option::None - require(_data.length > 0, "No relayers"); - - // Option::Some(Reayler[]) - // _data checking - (uint256 relayersCount, uint8 mode) = ScaleCodec.decodeUintCompact( - _data - ); - require(relayersCount > 0, "No relayers"); - require(mode < 3, "Wrong compact mode"); // Now, mode 3 is not supported yet - uint8 lengthOfPrefixBytes = uint8(2 ** mode); - require( - _data.length >= lengthOfPrefixBytes + relayersCount * 52, - "No enough data" - ); - - // get the bytes of the last Relayer, then decode - Relayer memory relayer = decodeRelayer( - Bytes.substr(_data, lengthOfPrefixBytes + 52 * (relayersCount - 1)) - ); - return relayer; - } - - //////////////////////////////////// - // OutboundLaneData - //////////////////////////////////// - struct OutboundLaneData { - uint64 oldestUnprunedNonce; - uint64 latestReceivedNonce; - uint64 latestGeneratedNonce; - } - - // 24 bytes - function decodeOutboundLaneData( - bytes memory _data - ) internal pure returns (OutboundLaneData memory) { - require( - _data.length >= 24, - "The data is not enough to decode OutboundLaneData" - ); - - uint64 oldestUnprunedNonce = ScaleCodec.decodeUint64( - Bytes.substr(_data, 0, 8) - ); - uint64 latestReceivedNonce = ScaleCodec.decodeUint64( - Bytes.substr(_data, 8, 8) - ); - uint64 latestGeneratedNonce = ScaleCodec.decodeUint64( - Bytes.substr(_data, 16, 8) - ); - - return - OutboundLaneData( - oldestUnprunedNonce, - latestReceivedNonce, - latestGeneratedNonce - ); - } - - //////////////////////////////////// - // DeliveredMessages - //////////////////////////////////// - struct DeliveredMessages { - uint64 begin; - uint64 end; - BitVecU8 dispatchResults; - } - - function decodeDeliveredMessages( - bytes memory _data - ) internal pure returns (DeliveredMessages memory) { - uint64 begin = ScaleCodec.decodeUint64(Bytes.substr(_data, 0, 8)); - uint64 end = ScaleCodec.decodeUint64(Bytes.substr(_data, 8, 8)); - BitVecU8 memory dispatchResults = decodeBitVecU8( - Bytes.substr(_data, 16) - ); - - return DeliveredMessages(begin, end, dispatchResults); - } - - function getBytesLengthOfDeliveredMessages( - DeliveredMessages memory deliveredMessages - ) internal pure returns (uint) { - return 16 + deliveredMessages.dispatchResults.bytesLength; - } - - //////////////////////////////////// - // UnrewardedRelayer - //////////////////////////////////// - struct UnrewardedRelayer { - address relayer; - DeliveredMessages messages; - } - - function decodeUnrewardedRelayer( - bytes memory _data - ) internal pure returns (UnrewardedRelayer memory) { - address relayer = toAddress(_data, 0); - DeliveredMessages memory messages = decodeDeliveredMessages( - Bytes.substr(_data, 20) - ); - - return UnrewardedRelayer(relayer, messages); - } - - function getBytesLengthOfUnrewardedRelayer( - UnrewardedRelayer memory unrewardedRelayer - ) internal pure returns (uint) { - uint bytesLengthOfmessages = getBytesLengthOfDeliveredMessages( - unrewardedRelayer.messages - ); - return 20 + bytesLengthOfmessages; - } - - function toAddress( - bytes memory _bytes, - uint256 _start - ) internal pure returns (address) { - require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); - address tempAddress; - - assembly { - tempAddress := div( - mload(add(add(_bytes, 0x20), _start)), - 0x1000000000000000000000000 - ) - } - - return tempAddress; - } - - //////////////////////////////////// - // InboundLaneData - //////////////////////////////////// - // struct InboundLaneData { - // VecDeque relayers; - // uint64 last_confirmed_nonce; - // } - struct InboundLaneData { - UnrewardedRelayer[] relayers; - uint64 lastConfirmedNonce; - } - - function decodeInboundLaneData( - bytes memory _data - ) internal pure returns (InboundLaneData memory) { - (uint256 numberOfRelayers, uint8 mode) = ScaleCodec.decodeUintCompact( - _data - ); - require(mode < 3, "Wrong compact mode"); // Now, mode 3 is not supported yet - uint consumedLength = uint8(2 ** mode); - - InboundLaneData memory result = InboundLaneData( - new UnrewardedRelayer[](numberOfRelayers), - 0 - ); - - // decode relayers - for (uint i = 0; i < numberOfRelayers; i++) { - UnrewardedRelayer memory relayer = decodeUnrewardedRelayer( - Bytes.substr(_data, consumedLength) - ); - result.relayers[i] = relayer; - consumedLength = - consumedLength + - getBytesLengthOfUnrewardedRelayer(relayer); - } - - // decode lastConfirmedNonce - result.lastConfirmedNonce = ScaleCodec.decodeUint64( - Bytes.substr(_data, consumedLength) - ); - - return result; - } - - function getLastDeliveredNonceFromInboundLaneData( - bytes memory _data - ) internal pure returns (uint64) { - InboundLaneData memory inboundLaneData = decodeInboundLaneData(_data); - if (inboundLaneData.relayers.length == 0) { - return inboundLaneData.lastConfirmedNonce; - } else { - UnrewardedRelayer memory lastRelayer = inboundLaneData.relayers[ - inboundLaneData.relayers.length - 1 - ]; - return lastRelayer.messages.end; - } - } - - //////////////////////////////////// - // Message - //////////////////////////////////// - struct Message { - uint32 specVersion; - uint64 weightRefTime; - uint64 weightProofSize; - EnumItemWithAccountId origin; - EnumItemWithNull dispatchFeePayment; - bytes call; - } - - function encodeMessage( - Message memory _message - ) internal pure returns (bytes memory) { - return - abi.encodePacked( - ScaleCodec.encode32(_message.specVersion), - // weight - ScaleCodec.encodeUintCompact(_message.weightRefTime), - ScaleCodec.encodeUintCompact(_message.weightProofSize), - // origin - _message.origin.index, - _message.origin.accountId, - // dispatchFeePayment - _message.dispatchFeePayment.index, - ScaleCodec.encodeBytes(_message.call) - ); - } -} - -// File @darwinia/contracts-periphery/contracts/s2s/types/PalletBridgeMessages.sol@vv2.1.1-fix2 -// License-Identifier: MIT - - - -library PalletBridgeMessages { - struct SendMessageCall { - bytes2 callIndex; // pallet index and call func index - bytes4 laneId; - bytes message; - uint128 deliveryAndDispatchFee; - } - - function encodeSendMessageCall(SendMessageCall memory _call) - internal - pure - returns (bytes memory) - { - return - abi.encodePacked( - _call.callIndex, - _call.laneId, - _call.message, - ScaleCodec.encode128(_call.deliveryAndDispatchFee) - ); - } -} - -// File @darwinia/contracts-periphery/contracts/s2s/MessageLib.sol@vv2.1.1-fix2 -// License-Identifier: MIT - - - - - - -library MessageLib { - bytes public constant ACCOUNT_DERIVATION_PREFIX = - "pallet-bridge/account-derivation/account"; - - // Send message over lane by calling the `send_message` dispatch call on - // the source chain which is identified by the `callIndex` param. - // Note: `XxxMessages`.`send_message`, the origin must equals to the origin in the message - function sendMessage( - address _srcDispatchPrecompileAddress, - bytes2 _callIndex, - bytes4 _laneId, - uint256 _deliveryAndDispatchFee, - bytes memory _message - ) internal { - // encode send_message call - PalletBridgeMessages.SendMessageCall - memory sendMessageCall = PalletBridgeMessages.SendMessageCall( - _callIndex, - _laneId, - _message, - uint128(_deliveryAndDispatchFee) - ); - - bytes memory sendMessageCallEncoded = PalletBridgeMessages - .encodeSendMessageCall(sendMessageCall); - - // dispatch the send_message call - dispatch( - _srcDispatchPrecompileAddress, - sendMessageCallEncoded, - "Dispatch send_message failed" - ); - } - - // Build the scale encoded message for the target chain. - function buildMessage( - uint32 _specVersion, - uint64 _weight, - bytes memory _call - ) internal view returns (bytes memory) { - // enum CallOrigin - // 0: SourceRoot - // 1: TargetAccount - // 2: SourceAccount - CommonTypes.EnumItemWithAccountId memory origin = CommonTypes - .EnumItemWithAccountId( - 2, // CallOrigin::SourceAccount - address(this) // UserApp contract address - ); - - // enum DispatchFeePayment - // 0: AtSourceChain - // 1: AtTargetChain - CommonTypes.EnumItemWithNull memory dispatchFeePayment = CommonTypes - .EnumItemWithNull(0); // DispatchFeePayment::AtSourceChain - - return - CommonTypes.encodeMessage( - CommonTypes.Message( - _specVersion, - _weight, - 0, - origin, - dispatchFeePayment, - _call - ) - ); - } - - // Get market fee from state storage of the substrate chain - function marketFee( - address _srcStoragePrecompileAddress, - bytes32 _storageKey - ) internal view returns (uint128) { - bytes memory data = getStateStorage( - _srcStoragePrecompileAddress, - abi.encodePacked(_storageKey), - "Get market fee failed" - ); - - CommonTypes.Relayer memory relayer = CommonTypes.getLastRelayerFromVec( - data - ); - return relayer.fee; - } - - // Get the latest nonce from state storage - function latestNonce( - address _srcStoragePrecompileAddress, - bytes32 _storageKey, - bytes4 _laneId - ) internal view returns (uint64) { - // 1. Get `OutboundLaneData` from storage - // Full storage key == storageKey + Blake2_128Concat(laneId) - bytes memory hashedLaneId = Hash.blake2b128Concat( - abi.encodePacked(_laneId) - ); - bytes memory fullStorageKey = abi.encodePacked( - _storageKey, - hashedLaneId - ); - - // Do get data by calling state storage precompile - bytes memory data = getStateStorage( - _srcStoragePrecompileAddress, - fullStorageKey, - "Get OutboundLaneData failed" - ); - - // 2. Decode `OutboundLaneData` and return the latest nonce - CommonTypes.OutboundLaneData memory outboundLaneData = CommonTypes - .decodeOutboundLaneData(data); - return outboundLaneData.latestGeneratedNonce; - } - - function deriveAccountId( - bytes4 _srcChainId, - bytes32 _accountId - ) internal view returns (bytes32) { - bytes memory data = abi.encodePacked( - bytes1(0xa0), // compact length of ACCOUNT_DERIVATION_PREFIX - ACCOUNT_DERIVATION_PREFIX, - _srcChainId, - _accountId - ); - return Hash.blake2bHash(data); - } - - function revertIfFailed( - bool _success, - bytes memory _resultData, - string memory _revertMsg - ) internal pure { - if (!_success) { - if (_resultData.length > 0) { - assembly { - let resultDataSize := mload(_resultData) - revert(add(32, _resultData), resultDataSize) - } - } else { - revert(_revertMsg); - } - } - } - - event DispatchCall(bytes); - - // Dispatch pallet dispatch-call - function dispatch( - address _srcDispatchPrecompileAddress, - bytes memory _callEncoded, - string memory _errMsg - ) internal { - emit DispatchCall(_callEncoded); - // Dispatch the call - (bool success, bytes memory data) = _srcDispatchPrecompileAddress.call( - _callEncoded - ); - revertIfFailed(success, data, _errMsg); - } - - function deriveSender( - bytes4 _srcChainId, - address _srcMessageSender - ) internal view returns (address) { - // H160(sender on the sourc chain) > AccountId32 - bytes32 derivedSubstrateAddress = AccountId.deriveSubstrateAddress( - _srcMessageSender - ); - - // AccountId32 > derived AccountId32 - bytes32 derivedAccountId = deriveAccountId( - _srcChainId, - derivedSubstrateAddress - ); - - // derived AccountId32 > H160 - address result = AccountId.deriveEthereumAddress(derivedAccountId); - - return result; - } - - // Get the last delivered nonce from the state storage of the target chain's inbound lane - function lastDeliveredNonce( - address _tgtStoragePrecompileAddress, - bytes32 _storageKey, - bytes4 _inboundLaneId - ) internal view returns (uint64) { - // 1. Get `inboundLaneData` from storage - // Full storage key == storageKey + Blake2_128Concat(laneId) - bytes memory hashedLaneId = Hash.blake2b128Concat( - abi.encodePacked(_inboundLaneId) - ); - bytes memory fullStorageKey = abi.encodePacked( - _storageKey, - hashedLaneId - ); - - // Do get data by calling state storage precompile - bytes memory data = getStateStorage( - _tgtStoragePrecompileAddress, - fullStorageKey, - "Get InboundLaneData failed" - ); - - // 2. Decode `InboundLaneData` and return the last delivered nonce - return CommonTypes.getLastDeliveredNonceFromInboundLaneData(data); - } - - function getStateStorage( - address _storagePrecompileAddress, - bytes memory _storageKey, - string memory _failedMsg - ) internal view returns (bytes memory) { - (bool success, bytes memory data) = _storagePrecompileAddress - .staticcall( - abi.encodeWithSelector( - IStateStorage.state_storage.selector, - _storageKey - ) - ); - - // TODO: Use try/catch instead for error - revertIfFailed(success, data, _failedMsg); - - return abi.decode(data, (bytes)); - } -} - -// File @darwinia/contracts-periphery/contracts/s2s/types/PalletEthereum.sol@vv2.1.1-fix2 -// License-Identifier: MIT - - - - -library PalletEthereum { - struct TransactCall { - bytes2 callIndex; - EnumItemTransactionV2WithLegacyTransaction transaction; - } - - function encodeTransactCall(TransactCall memory _call) - internal - pure - returns (bytes memory) - { - return - abi.encodePacked( - _call.callIndex, - encodeEnumItemTransactionV2WithLegacyTransaction( - _call.transaction - ) - ); - } - - struct MessageTransactCall { - bytes2 callIndex; - EnumItemTransactionV2WithLegacyTransaction transaction; - } - - function encodeMessageTransactCall(MessageTransactCall memory _call) - internal - pure - returns (bytes memory) - { - return - abi.encodePacked( - _call.callIndex, - encodeEnumItemTransactionV2WithLegacyTransaction( - _call.transaction - ) - ); - } - - struct EnumItemTransactionActionWithAddress { - uint8 index; - address h160; - } - - function encodeEnumItemTransactionActionWithAddress( - EnumItemTransactionActionWithAddress memory _item - ) internal pure returns (bytes memory) { - return abi.encodePacked(_item.index, _item.h160); - } - - struct LegacyTransaction { - uint256 nonce; - uint256 gasPrice; - uint256 gasLimit; - EnumItemTransactionActionWithAddress action; - uint256 value; - bytes input; - uint64 v; - bytes32 r; - bytes32 s; - } - - function encodeLegacyTransaction(LegacyTransaction memory _transaction) - internal - pure - returns (bytes memory) - { - return - abi.encodePacked( - ScaleCodec.encode256(_transaction.nonce), - ScaleCodec.encode256(_transaction.gasPrice), - ScaleCodec.encode256(_transaction.gasLimit), - encodeEnumItemTransactionActionWithAddress(_transaction.action), - ScaleCodec.encode256(_transaction.value), - ScaleCodec.encodeBytes(_transaction.input), - ScaleCodec.encode64(_transaction.v), - _transaction.r, - _transaction.s - ); - } - - struct EnumItemTransactionV2WithLegacyTransaction { - uint8 index; - LegacyTransaction legacyTransaction; - } - - function encodeEnumItemTransactionV2WithLegacyTransaction( - EnumItemTransactionV2WithLegacyTransaction memory _item - ) internal pure returns (bytes memory) { - return - abi.encodePacked( - _item.index, - encodeLegacyTransaction(_item.legacyTransaction) - ); - } - - function buildTransactionV2( - uint256 _nonce, - uint256 _gasPrice, - uint256 _gasLimit, - address _to, - uint256 _value, - uint64 _smartChainId, - bytes memory _input - ) - internal - pure - returns (EnumItemTransactionV2WithLegacyTransaction memory) - { - LegacyTransaction memory transaction = LegacyTransaction( - _nonce, - _gasPrice, - _gasLimit, - PalletEthereum.EnumItemTransactionActionWithAddress( - 0, - _to - ), - _value, - _input, - _smartChainId * 2 + 36, // v - 0x3737373737373737373737373737373737373737373737373737373737373737, // r - 0x3737373737373737373737373737373737373737373737373737373737373737 // s - ); - - return - EnumItemTransactionV2WithLegacyTransaction( - 0, // enum index - transaction // legacyTransaction - ); - } - - function buildTransactionV2ForMessageTransact( - uint256 _gasLimit, - address _to, - uint64 _smartChainId, - bytes memory _input - ) - internal - pure - returns (EnumItemTransactionV2WithLegacyTransaction memory) - { - // nonce and gasPrice will be set by target chain - return buildTransactionV2(0, 0, _gasLimit, _to, 0, _smartChainId, _input); - } -} - -// File @darwinia/contracts-periphery/contracts/s2s/MessageEndpoint.sol@vv2.1.1-fix2 -// License-Identifier: MIT - - - -// srcDapp > endpoint[outboundLaneId] > substrate.send_message -// -> -// substrate.message_transact > remoteEndpoint[inboundLaneId] > TgtDapp.function -abstract contract MessageEndpoint { - // REMOTE - address public remoteEndpoint; - // message sender derived from remoteEndpoint - address public derivedMessageSender; - // call indices - bytes2 public remoteMessageTransactCallIndex; - // remote smart chain id - uint64 public remoteSmartChainId; - - // 1 gas ~= 18_750 weight - uint64 public constant REMOTE_WEIGHT_PER_GAS = 18_750; - - // LOCAL - // storage keys - bytes32 public storageKeyForMarketFee; - bytes32 public storageKeyForLatestNonce; - bytes32 public storageKeyForLastDeliveredNonce; - // call indices - bytes2 public sendMessageCallIndex; - - // lane ids - bytes4 public immutable OUTBOUND_LANE_ID; - bytes4 public immutable INBOUND_LANE_ID; - uint16 public immutable VERSION; - // precompile addresses - address public constant STORAGE_ADDRESS = - 0x0000000000000000000000000000000000000400; - address public constant DISPATCH_ADDRESS = - 0x0000000000000000000000000000000000000401; - - constructor(uint16 version, bytes4 outboundLaneId, bytes4 inboundLaneId) { - VERSION = version; - OUTBOUND_LANE_ID = outboundLaneId; - INBOUND_LANE_ID = inboundLaneId; - } - - /////////////////////////////// - // Outbound - /////////////////////////////// - function fee() public view returns (uint128) { - return MessageLib.marketFee(STORAGE_ADDRESS, storageKeyForMarketFee); - } - - // srcDapp > endpoint[outboundLaneId] > substrate.send_message - // -> - // substrate.message_transact(input) > remoteEndpoint[inboundLaneId] > TgtDapp.function - function _remoteExecute( - uint32 tgtSpecVersion, - address callReceiver, - bytes calldata callPayload, - uint256 gasLimit - ) internal returns (uint256) { - bytes memory input = abi.encodeWithSelector( - this.execute.selector, - callReceiver, - callPayload - ); - - return _remoteTransact(tgtSpecVersion, input, gasLimit); - } - - function _remoteTransact( - uint32 tgtSpecVersion, - bytes memory input, - uint256 gasLimit - ) internal returns (uint256) { - PalletEthereum.MessageTransactCall memory call = PalletEthereum - .MessageTransactCall( - // the call index of message_transact - remoteMessageTransactCallIndex, - // the evm transaction to transact - PalletEthereum.buildTransactionV2ForMessageTransact( - gasLimit, - remoteEndpoint, - remoteSmartChainId, - input - ) - ); - bytes memory callEncoded = PalletEthereum.encodeMessageTransactCall( - call - ); - - uint64 weight = uint64(gasLimit * REMOTE_WEIGHT_PER_GAS); - - return _remoteDispatch(tgtSpecVersion, callEncoded, weight); - } - - function _remoteDispatch( - uint32 tgtSpecVersion, - bytes memory tgtCallEncoded, - uint64 tgtCallWeight - ) internal returns (uint256) { - // Build the encoded message to be sent - bytes memory message = MessageLib.buildMessage( - tgtSpecVersion, - tgtCallWeight, - tgtCallEncoded - ); - - // Send the message - MessageLib.sendMessage( - DISPATCH_ADDRESS, - sendMessageCallIndex, - OUTBOUND_LANE_ID, - msg.value, - message - ); - - // Get nonce from storage - uint64 nonce = MessageLib.latestNonce( - STORAGE_ADDRESS, - storageKeyForLatestNonce, - OUTBOUND_LANE_ID - ); - - return encodeMessageId(OUTBOUND_LANE_ID, nonce); - } - - function _dispatch(bytes memory call) public { - MessageLib.dispatch(DISPATCH_ADDRESS, call, "!dispatch"); - } - - /////////////////////////////// - // Inbound - /////////////////////////////// - modifier onlyMessageSender() { - require( - derivedMessageSender == msg.sender, - "MessageEndpoint: Invalid sender" - ); - _; - } - - function execute( - address callReceiver, - bytes calldata callPayload - ) external onlyMessageSender { - if (_canBeExecuted(callReceiver, callPayload)) { - (bool success, ) = callReceiver.call(callPayload); - require(success, "MessageEndpoint: Call execution failed"); - } else { - revert("MessageEndpoint: Unapproved call"); - } - } - - // Check if the call can be executed - function _canBeExecuted( - address callReceiver, - bytes calldata callPayload - ) internal view virtual returns (bool); - - // Get the last delivered inbound message id - function lastDeliveredMessageId() public view returns (uint256) { - uint64 nonce = MessageLib.lastDeliveredNonce( - STORAGE_ADDRESS, - storageKeyForLastDeliveredNonce, - INBOUND_LANE_ID - ); - return encodeMessageId(INBOUND_LANE_ID, nonce); - } - - // Check if an inbound message has been delivered - function isMessageDelivered(uint256 messageId) public view returns (bool) { - (bytes4 laneId, uint64 nonce) = decodeMessageId(messageId); - uint64 lastNonce = MessageLib.lastDeliveredNonce( - STORAGE_ADDRESS, - storageKeyForLastDeliveredNonce, - laneId - ); - return nonce <= lastNonce; - } - - /////////////////////////////// - // Common functions - /////////////////////////////// - function decodeMessageId( - uint256 messageId - ) public view returns (bytes4, uint64) { - uint16 version = uint16(messageId >> 240); - require(version == VERSION, "MessageEndpoint: Invalid Version"); - return ( - bytes4(uint32(messageId >> 64)), - uint64(messageId & 0xffffffffffffffff) - ); - } - - function encodeMessageId( - bytes4 laneId, - uint64 nonce - ) public view returns (uint256) { - return - (uint256(uint32(laneId)) << 64) + - (uint256(VERSION) << 240) + - uint256(nonce); - } - - /////////////////////////////// - // Setters - /////////////////////////////// - function _setRemoteEndpoint( - bytes4 _remoteChainId, - address _remoteEndpoint - ) internal { - remoteEndpoint = _remoteEndpoint; - derivedMessageSender = MessageLib.deriveSender( - _remoteChainId, - _remoteEndpoint - ); - } - - function _setRemoteMessageTransactCallIndex( - bytes2 _remoteMessageTransactCallIndex - ) internal { - remoteMessageTransactCallIndex = _remoteMessageTransactCallIndex; - } - - function _setSendMessageCallIndex(bytes2 _sendMessageCallIndex) internal { - sendMessageCallIndex = _sendMessageCallIndex; - } - - function _setStorageKeyForMarketFee( - bytes32 _storageKeyForMarketFee - ) internal { - storageKeyForMarketFee = _storageKeyForMarketFee; - } - - function _setStorageKeyForLatestNonce( - bytes32 _storageKeyForLatestNonce - ) internal { - storageKeyForLatestNonce = _storageKeyForLatestNonce; - } - - function _setRemoteSmartChainId(uint64 _remoteSmartChainId) internal { - remoteSmartChainId = _remoteSmartChainId; - } - - function _setStorageKeyForLastDeliveredNonce( - bytes32 _storageKeyForLastDeliveredNonce - ) internal { - storageKeyForLastDeliveredNonce = _storageKeyForLastDeliveredNonce; - } -} - -// File contracts/mapping-token/v2/message-endpoints/DarwiniaSub2SubMessageEndpoint.sol -// License-Identifier: MIT - - -contract DarwiniaSub2SubMessageEndpoint is AccessController, MessageEndpoint { - constructor(uint16 _version, bytes4 _outboundLaneId, bytes4 _inboundLaneId) MessageEndpoint(_version, _outboundLaneId, _inboundLaneId) { - _initialize(msg.sender); - } - - function setRemoteHelix(bytes4 _remoteChainId, uint64 _remoteSmartChainId, address _remoteHelix) external onlyAdmin { - _setRemoteEndpoint(_remoteChainId, _remoteHelix); - _setRemoteSmartChainId(_remoteSmartChainId); - } - - function setRemoteCallIndex(bytes2 _remoteMessageTransactCallIndex) external onlyAdmin { - _setRemoteMessageTransactCallIndex(_remoteMessageTransactCallIndex); - } - - function setLocalCallInfo(bytes2 _callIndexOfSendMessage) external onlyAdmin { - _setSendMessageCallIndex(_callIndexOfSendMessage); - } - - function setLocalStorageKey( - bytes32 _srcStorageKeyForMarketFee, - bytes32 _srcStorageKeyForLatestNonce, - bytes32 _dstStorageKeyForLastDeliveredNonce - ) external onlyAdmin { - _setStorageKeyForMarketFee(_srcStorageKeyForMarketFee); - _setStorageKeyForLatestNonce(_srcStorageKeyForLatestNonce); - _setStorageKeyForLastDeliveredNonce(_dstStorageKeyForLastDeliveredNonce); - } - - function sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address receiver, - bytes calldata callPayload - ) external onlyCaller whenNotPaused payable returns(uint256) { - return _remoteExecute(remoteSpecVersion, receiver, callPayload, remoteReceiveGasLimit); - } - - function _canBeExecuted(address callReceiver, bytes calldata) internal view override whenNotPaused returns (bool) { - return hasRole(CALLEE_ROLE, callReceiver); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2sub/Erc20.sol b/helix-contract/flatten/sub2sub/Erc20.sol deleted file mode 100644 index 1a680ce4..00000000 --- a/helix-contract/flatten/sub2sub/Erc20.sol +++ /dev/null @@ -1,555 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 4/28/2023 - **/ - -pragma solidity ^0.8.10; - -// 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/access/Ownable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - -// 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) - - -// CAUTION -// This version of SafeMath should only be used with Solidity 0.8 or later, -// because it relies on the compiler's built in overflow checks. - -/** - * @dev Wrappers over Solidity's arithmetic operations. - * - * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler - * now has built in overflow checking. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - return a + b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - return a * b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b <= a, errorMessage); - return a - b; - } - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a / b; - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a % b; - } - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20.sol -// License-Identifier: MIT - - - -contract Erc20 is IERC20, Ownable { - using SafeMath for uint256; - - mapping (address => uint256) private _balances; - - mapping (address => mapping (address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string public name; - string public symbol; - uint8 public decimals; - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - _transferOwnership(_msgSender()); - } - - function totalSupply() public view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address account) public view override returns (uint256) { - return _balances[account]; - } - - function transfer(address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(msg.sender, recipient, amount); - return true; - } - - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _approve(msg.sender, spender, amount); - return true; - } - - function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(sender, recipient, amount); - _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")); - return true; - } - - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); - return true; - } - - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); - return true; - } - - function _transfer(address sender, address recipient, uint256 amount) internal virtual { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(sender, recipient, amount); - - _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); - _balances[recipient] = _balances[recipient].add(amount); - emit Transfer(sender, recipient, amount); - } - - // only factory contract can mint with the lock proof from ethereum - function mint(address account, uint256 amount) external onlyOwner { - _mint(account, amount); - } - - function burn(address account, uint256 amount) external { - if (account != msg.sender && owner() != msg.sender && _allowances[account][msg.sender] != type(uint256).max) { - _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: decreased allowance below zero")); - } - _burn(account, amount); - } - - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); - } - - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); - _totalSupply = _totalSupply.sub(amount); - emit Transfer(account, address(0), amount); - } - - function _approve(address owner, address spender, uint256 amount) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2sub/Erc20Sub2SubBacking.sol b/helix-contract/flatten/sub2sub/Erc20Sub2SubBacking.sol deleted file mode 100644 index 76cd3f53..00000000 --- a/helix-contract/flatten/sub2sub/Erc20Sub2SubBacking.sol +++ /dev/null @@ -1,2181 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 4/28/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/utils/DailyLimit.sol -// License-Identifier: MIT - - -/// @title relay with daily limit - Allows the relay to mint token in a daily limit. -contract DailyLimit { - - event DailyLimitChange(address token, uint dailyLimit); - - mapping(address => uint) public dailyLimit; - // deprecated, slot for upgrade - mapping(address => uint) public _slotReserved; - mapping(address => uint) public spentToday; - - uint constant public SPEND_BIT_LENGTH = 192; - uint constant public LASTDAY_BIT_LENGTH = 64; - - /// ==== Internal functions ==== - - /// @dev Contract constructor sets initial owners, required number of confirmations and daily mint limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei, which can be mint without confirmations on a daily basis. - function _setDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - } - - /// @dev Allows to change the daily limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei. - function _changeDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - emit DailyLimitChange(_token, _dailyLimit); - } - - /// @dev Allows to change the daily limit. - /// @param token Token address. - /// @param amount Amount in wei. - function expendDailyLimit(address token, uint amount) - internal - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - require(amount <= dailyLimit[token], "DailyLimit: amount exceed daily limit"); - spentToday[token] = (block.timestamp << SPEND_BIT_LENGTH) + amount; - return; - } - require(lastspent + amount <= dailyLimit[token] && amount <= dailyLimit[token], "DailyLimit: exceed daily limit"); - spentToday[token] = spentInfo + amount; - } - - /// ==== Web3 call functions ==== - - /// @dev Returns maximum withdraw amount. - /// @param token Token address. - /// @return Returns amount. - function calcMaxWithdraw(address token) - public - view - returns (uint) - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - return dailyLimit[token]; - } - - if (dailyLimit[token] < lastspent) { - return 0; - } - - return dailyLimit[token] - lastspent; - } -} - -// File contracts/mapping-token/interfaces/IGuard.sol -// License-Identifier: MIT - - -interface IGuard { - function deposit(uint256 id, address token, address recipient, uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IErc20MappingTokenFactory.sol -// License-Identifier: MIT - - -interface IErc20MappingTokenFactory { - function newErc20Contract( - address originalToken, - string memory bridgedChainName, - string memory name, - string memory symbol, - uint8 decimals, - uint256 dailyLimit - ) external returns (address mappingToken); - function issueMappingToken( - address originalToken, - address recipient, - uint256 amount - ) external; -} - -// File contracts/mapping-token/interfaces/IBacking.sol -// License-Identifier: MIT - - -interface IBacking { - function unlockFromRemote( - address originalToken, - address recipient, - uint256 amount) external; -} - -interface IBackingSupportNative { - function unlockFromRemoteNative( - address recipient, - uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IHelixApp.sol -// License-Identifier: MIT - - -interface IHelixAppSupportWithdrawFailed { - function handleUnlockFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; - function handleUnlockFailureFromRemoteNative( - uint256 messageId, - address sender, - uint256 amount - ) external; - function handleIssuingFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; -} - -// File contracts/mapping-token/interfaces/IHelixMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixMessageEndpoint { - function sendMessage(address receiver, bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IHelixSub2SubMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixSub2SubMessageEndpoint is IHelixMessageEndpoint { - function fee() external view returns (uint256); - function lastDeliveredMessageId() external view returns (uint256); - function isMessageDelivered(uint256 messageId) external view returns(bool); - function sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address receiver, - bytes calldata encoded) external payable returns (uint256); -} - -// 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/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/AccessController.sol -// License-Identifier: MIT - - -contract AccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - bytes32 public constant CALLER_ROLE = keccak256("CALLER_ROLE"); - bytes32 public constant CALLEE_ROLE = keccak256("CALLEE_ROLE"); - - // access controller - // admin is helix Dao - modifier onlyAdmin() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "AccessController:Bad admin role"); - _; - } - - // operator - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "AccessController:Bad operator role"); - _; - } - - modifier onlyCaller() { - require(hasRole(CALLER_ROLE, msg.sender), "AccessController:Bad caller role"); - _; - } - - modifier onlyCallee() { - require(hasRole(CALLEE_ROLE, msg.sender), "AccessController:Bad callee role"); - _; - } - - function _initialize(address admin) internal { - _setRoleAdmin(CALLER_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(CALLEE_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, admin); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/Backing.sol -// License-Identifier: MIT - - -contract Backing is AccessController, Initializable { - address public messageEndpoint; - address public remoteMappingTokenFactory; - - uint256 internal locked; - modifier nonReentrant { - require(locked == 0, "backing: locked"); - locked = 1; - _; - locked = 0; - } - - modifier onlyMessageEndpoint() { - require(messageEndpoint == msg.sender, "Backing:Bad message handle"); - _; - } - - function initialize(address _messageEndpoint) public initializer { - messageEndpoint = _messageEndpoint; - _initialize(msg.sender); - } - - function _setMessageEndpoint(address _messageEndpoint) internal { - messageEndpoint = _messageEndpoint; - } - - function setRemoteMappingTokenFactory(address _remoteMappingTokenFactory) external onlyAdmin { - remoteMappingTokenFactory = _remoteMappingTokenFactory; - } -} - -// 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/structs/BitMaps.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol) - -/** - * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. - * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. - */ -library BitMaps { - struct BitMap { - mapping(uint256 => uint256) _data; - } - - /** - * @dev Returns whether the bit at `index` is set. - */ - function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - return bitmap._data[bucket] & mask != 0; - } - - /** - * @dev Sets the bit at `index` to the boolean `value`. - */ - function setTo( - BitMap storage bitmap, - uint256 index, - bool value - ) internal { - if (value) { - set(bitmap, index); - } else { - unset(bitmap, index); - } - } - - /** - * @dev Sets the bit at `index`. - */ - function set(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] |= mask; - } - - /** - * @dev Unsets the bit at `index`. - */ - function unset(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] &= ~mask; - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20Sub2SubBacking.sol -// License-Identifier: MIT - - - - - - - - - - -contract Erc20Sub2SubBacking is Backing, DailyLimit, IBacking { - struct LockedInfo { - bytes32 hash; - bool hasRefundForFailed; - } - - address public guard; - string public chainName; - uint256 public helixFee; - - // (transferId => LockedInfo) - mapping(uint256 => LockedInfo) public lockedMessages; - BitMaps.BitMap unlockedMessages; - address public wToken; - - event NewErc20TokenRegistered(uint256 transferId, address token); - event TokenLocked(uint256 transferId, bool isNative, address token, address sender, address recipient, uint256 amount, uint256 fee); - event TokenUnlocked(uint256 transferId, bool isNative, address token, address recipient, uint256 amount); - event RemoteIssuingFailure(uint256 refundId, uint256 transferId, uint256 fee); - event TokenUnlockedForFailed(uint256 transferId, bool isNative, address token, address recipient, uint256 amount); - - receive() external payable {} - - function setMessageEndpoint(address _messageEndpoint) external onlyAdmin { - _setMessageEndpoint(_messageEndpoint); - } - - function setChainName(string memory _chainName) external onlyAdmin { - chainName = _chainName; - } - - function changeDailyLimit(address token, uint amount) public onlyAdmin { - _changeDailyLimit(token, amount); - } - - function setHelixFee(uint256 _helixFee) external onlyAdmin { - helixFee = _helixFee; - } - - function updateGuard(address newGuard) external onlyAdmin { - guard = newGuard; - } - - function setWToken(address _wToken) external onlyAdmin { - wToken = _wToken; - } - - function fee() external view returns(uint256) { - return IHelixSub2SubMessageEndpoint(messageEndpoint).fee() + helixFee; - } - - function _sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - bytes memory message, - uint256 prepaid - ) internal nonReentrant returns(uint256, uint256) { - uint256 bridgeFee = IHelixSub2SubMessageEndpoint(messageEndpoint).fee(); - uint256 totalFee = bridgeFee + helixFee; - require(prepaid >= totalFee, "Backing:the fee is not enough"); - if (prepaid > totalFee) { - // refund fee to msgSender - payable(msg.sender).transfer(prepaid - totalFee); - } - uint256 transferId = IHelixSub2SubMessageEndpoint(messageEndpoint).sendMessage{value: bridgeFee}( - remoteSpecVersion, - remoteReceiveGasLimit, - remoteMappingTokenFactory, - message); - return (transferId, totalFee); - } - - /** - * @notice reigister new erc20 token to the bridge. Only owner can do this. - * @param token the original token address - * @param name the name of the original token - * @param symbol the symbol of the original token - * @param decimals the decimals of the original token - */ - function register( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address token, - string memory name, - string memory symbol, - uint8 decimals, - uint256 dailyLimit - ) external payable onlyOperator { - bytes memory newErc20Contract = abi.encodeWithSelector( - IErc20MappingTokenFactory.newErc20Contract.selector, - token, - chainName, - name, - symbol, - decimals, - dailyLimit - ); - (uint256 transferId,) = _sendMessage( - remoteSpecVersion, - remoteReceiveGasLimit, - newErc20Contract, - msg.value - ); - _changeDailyLimit(token, dailyLimit); - emit NewErc20TokenRegistered(transferId, token); - } - - function _lockAndRemoteIssuing( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address token, - address recipient, - uint256 amount, - uint256 prepaid, - bool isNative - ) internal { - bytes memory issueMappingToken = abi.encodeWithSelector( - IErc20MappingTokenFactory.issueMappingToken.selector, - token, - recipient, - amount - ); - (uint256 transferId, uint256 totalFee) = _sendMessage( - remoteSpecVersion, - remoteReceiveGasLimit, - issueMappingToken, - prepaid - ); - require(lockedMessages[transferId].hash == bytes32(0), "backing: message exist"); - bytes32 lockMessageHash = hash(abi.encodePacked(transferId, token, msg.sender, amount)); - lockedMessages[transferId] = LockedInfo(lockMessageHash, false); - emit TokenLocked(transferId, isNative, token, msg.sender, recipient, amount, totalFee); - } - - - /** - * @notice lock original token and issuing mapping token from bridged chain - * @dev maybe some tokens will take some fee when transfer - * @param token the original token address - * @param recipient the recipient who will receive the issued mapping token - * @param amount amount of the locked token - */ - function lockAndRemoteIssuing( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address token, - address recipient, - uint256 amount - ) external payable whenNotPaused { - require(IERC20(token).transferFrom(msg.sender, address(this), amount), "Backing:transfer tokens failed"); - _lockAndRemoteIssuing( - remoteSpecVersion, - remoteReceiveGasLimit, - token, - recipient, - amount, - msg.value, - false); - } - - function lockAndRemoteIssuingNative( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address recipient, - uint256 amount - ) external payable whenNotPaused { - IWToken(wToken).deposit{value: amount}(); - _lockAndRemoteIssuing( - remoteSpecVersion, - remoteReceiveGasLimit, - wToken, - recipient, - amount, - msg.value - amount, - true); - } - - /** - * @notice this will be called by inboundLane when the remote mapping token burned and want to unlock the original token - * @param token the original token address - * @param recipient the recipient who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function unlockFromRemote( - address token, - address recipient, - uint256 amount - ) public onlyMessageEndpoint whenNotPaused { - expendDailyLimit(token, amount); - // current message id is last message id + 1 - uint256 transferId = IHelixSub2SubMessageEndpoint(messageEndpoint).lastDeliveredMessageId() + 1; - require(BitMaps.get(unlockedMessages, transferId) == false, "Backing:message has been accepted"); - BitMaps.set(unlockedMessages, transferId); - if (guard != address(0)) { - uint allowance = IERC20(token).allowance(address(this), guard); - require(IERC20(token).approve(guard, amount + allowance), "Backing:approve token transfer to guard failed"); - IGuard(guard).deposit(transferId, token, recipient, amount); - } else { - require(IERC20(token).transfer(recipient, amount), "Backing:unlock transfer failed"); - } - emit TokenUnlocked(transferId, false, token, recipient, amount); - } - - /** - * @notice this will be called by inboundLane when the remote mapping token burned and want to unlock the original native token - * @param recipient the recipient who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function unlockFromRemoteNative( - address payable recipient, - uint256 amount - ) public onlyMessageEndpoint whenNotPaused { - expendDailyLimit(wToken, amount); - uint256 transferId = IHelixSub2SubMessageEndpoint(messageEndpoint).lastDeliveredMessageId() + 1; - require(BitMaps.get(unlockedMessages, transferId) == false, "Backing:message has been accepted"); - BitMaps.set(unlockedMessages, transferId); - if (guard != address(0)) { - uint allowance = IERC20(wToken).allowance(address(this), guard); - require(IERC20(wToken).approve(guard, amount + allowance), "Backing:approve token transfer to guard failed"); - IGuard(guard).deposit(transferId, wToken, recipient, amount); - } else { - IWToken(wToken).withdraw(amount); - recipient.transfer(amount); - } - emit TokenUnlocked(transferId, true, wToken, recipient, amount); - } - - function _handleUnlockFailureFromRemote( - uint256 transferId, - address token, - address originSender, - uint256 amount - ) internal { - LockedInfo memory lockedMessage = lockedMessages[transferId]; - require(lockedMessage.hasRefundForFailed == false, "Backing: the locked message has been refund"); - bytes32 messageHash = hash(abi.encodePacked(transferId, token, originSender, amount)); - require(lockedMessage.hash == messageHash, "Backing: message is not matched"); - lockedMessages[transferId].hasRefundForFailed = true; - } - - /** - * @notice this will be called by messageEndpoint when the remote issue failed and want to unlock the original token - * @param token the original token address - * @param originSender the originSender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function handleUnlockFailureFromRemote( - uint256 transferId, - address token, - address originSender, - uint256 amount - ) external onlyMessageEndpoint whenNotPaused { - _handleUnlockFailureFromRemote(transferId, token, originSender, amount); - require(IERC20(token).transfer(originSender, amount), "Backing:unlock transfer failed"); - emit TokenUnlockedForFailed(transferId, false, token, originSender, amount); - } - - /** - * @notice this will be called by messageEndpoint when the remote issue failed and want to unlock the original native token - * @param originSender the originSender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function handleUnlockFailureFromRemoteNative( - uint256 transferId, - address originSender, - uint256 amount - ) external onlyMessageEndpoint whenNotPaused { - _handleUnlockFailureFromRemote(transferId, wToken, originSender, amount); - IWToken(wToken).withdraw(amount); - payable(originSender).transfer(amount); - emit TokenUnlockedForFailed(transferId, true, wToken, originSender, amount); - } - - function remoteIssuingFailure( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - uint256 transferId, - address mappingToken, - address originalSender, - uint256 amount - ) external payable whenNotPaused { - // must not exist in successful issue list - require(BitMaps.get(unlockedMessages, transferId) == false, "Backing:success message can't refund for failed"); - // must has been checked by message layer - bool messageChecked = IHelixSub2SubMessageEndpoint(messageEndpoint).isMessageDelivered(transferId); - require(messageChecked, "Backing:the message is not checked by message layer"); - bytes memory unlockForFailed = abi.encodeWithSelector( - IHelixAppSupportWithdrawFailed.handleIssuingFailureFromRemote.selector, - transferId, - mappingToken, - originalSender, - amount - ); - (uint256 refundId, uint256 totalFee) = _sendMessage( - remoteSpecVersion, - remoteReceiveGasLimit, - unlockForFailed, - msg.value - ); - emit RemoteIssuingFailure(refundId, transferId, totalFee); - } - - /** - * @notice this should not be used unless there is a non-recoverable error in the bridge or the target chain - * we use this to protect user's asset from being locked up - */ - function rescueFunds( - address token, - address recipient, - uint256 amount - ) external onlyAdmin { - IERC20(token).transfer(recipient, amount); - } - - function withdrawFee( - address payable recipient, - uint256 amount - ) external onlyAdmin { - recipient.transfer(amount); - } - - function hash(bytes memory value) public pure returns (bytes32) { - return sha256(value); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2sub/Erc20Sub2SubMappingTokenFactory.sol b/helix-contract/flatten/sub2sub/Erc20Sub2SubMappingTokenFactory.sol deleted file mode 100644 index ff9ffbe8..00000000 --- a/helix-contract/flatten/sub2sub/Erc20Sub2SubMappingTokenFactory.sol +++ /dev/null @@ -1,2662 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 4/28/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/utils/DailyLimit.sol -// License-Identifier: MIT - - -/// @title relay with daily limit - Allows the relay to mint token in a daily limit. -contract DailyLimit { - - event DailyLimitChange(address token, uint dailyLimit); - - mapping(address => uint) public dailyLimit; - // deprecated, slot for upgrade - mapping(address => uint) public _slotReserved; - mapping(address => uint) public spentToday; - - uint constant public SPEND_BIT_LENGTH = 192; - uint constant public LASTDAY_BIT_LENGTH = 64; - - /// ==== Internal functions ==== - - /// @dev Contract constructor sets initial owners, required number of confirmations and daily mint limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei, which can be mint without confirmations on a daily basis. - function _setDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - } - - /// @dev Allows to change the daily limit. - /// @param _token Token address. - /// @param _dailyLimit Amount in wei. - function _changeDailyLimit(address _token, uint _dailyLimit) - internal - { - require(_dailyLimit < type(uint192).max, "DaliyLimit: overflow uint192"); - dailyLimit[_token] = _dailyLimit; - emit DailyLimitChange(_token, _dailyLimit); - } - - /// @dev Allows to change the daily limit. - /// @param token Token address. - /// @param amount Amount in wei. - function expendDailyLimit(address token, uint amount) - internal - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - require(amount <= dailyLimit[token], "DailyLimit: amount exceed daily limit"); - spentToday[token] = (block.timestamp << SPEND_BIT_LENGTH) + amount; - return; - } - require(lastspent + amount <= dailyLimit[token] && amount <= dailyLimit[token], "DailyLimit: exceed daily limit"); - spentToday[token] = spentInfo + amount; - } - - /// ==== Web3 call functions ==== - - /// @dev Returns maximum withdraw amount. - /// @param token Token address. - /// @return Returns amount. - function calcMaxWithdraw(address token) - public - view - returns (uint) - { - uint spentInfo = spentToday[token]; - uint lastday = spentInfo >> SPEND_BIT_LENGTH; - uint lastspent = spentInfo << LASTDAY_BIT_LENGTH >> LASTDAY_BIT_LENGTH; - if (block.timestamp > lastday + 24 hours) { - return dailyLimit[token]; - } - - if (dailyLimit[token] < lastspent) { - return 0; - } - - return dailyLimit[token] - lastspent; - } -} - -// File contracts/mapping-token/interfaces/IGuard.sol -// License-Identifier: MIT - - -interface IGuard { - function deposit(uint256 id, address token, address recipient, uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IHelixMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixMessageEndpoint { - function sendMessage(address receiver, bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IHelixSub2SubMessageEndpoint.sol -// License-Identifier: MIT - - -interface IHelixSub2SubMessageEndpoint is IHelixMessageEndpoint { - function fee() external view returns (uint256); - function lastDeliveredMessageId() external view returns (uint256); - function isMessageDelivered(uint256 messageId) external view returns(bool); - function sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address receiver, - bytes calldata encoded) external payable returns (uint256); -} - -// File contracts/mapping-token/interfaces/IBacking.sol -// License-Identifier: MIT - - -interface IBacking { - function unlockFromRemote( - address originalToken, - address recipient, - uint256 amount) external; -} - -interface IBackingSupportNative { - function unlockFromRemoteNative( - address recipient, - uint256 amount) external; -} - -// File contracts/mapping-token/interfaces/IErc20MappingTokenFactory.sol -// License-Identifier: MIT - - -interface IErc20MappingTokenFactory { - function newErc20Contract( - address originalToken, - string memory bridgedChainName, - string memory name, - string memory symbol, - uint8 decimals, - uint256 dailyLimit - ) external returns (address mappingToken); - function issueMappingToken( - address originalToken, - address recipient, - uint256 amount - ) external; -} - -// File contracts/mapping-token/interfaces/IHelixApp.sol -// License-Identifier: MIT - - -interface IHelixAppSupportWithdrawFailed { - function handleUnlockFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; - function handleUnlockFailureFromRemoteNative( - uint256 messageId, - address sender, - uint256 amount - ) external; - function handleIssuingFailureFromRemote( - uint256 messageId, - address token, - address sender, - uint256 amount - ) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @zeppelin-solidity/contracts/access/IAccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) - - -/** - * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. - */ -interface IAccessControlEnumerable is IAccessControl { - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) external view returns (address); - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) external view returns (uint256); -} - -// 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/utils/introspection/IERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File @zeppelin-solidity/contracts/utils/introspection/ERC165.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -// File @zeppelin-solidity/contracts/utils/Strings.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/access/AccessControl.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) - - - - - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(account), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} - -// File @zeppelin-solidity/contracts/utils/structs/EnumerableSet.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// File @zeppelin-solidity/contracts/access/AccessControlEnumerable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) - - - - -/** - * @dev Extension of {AccessControl} that allows enumerating the members of each role. - */ -abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { - using EnumerableSet for EnumerableSet.AddressSet; - - mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns one of the accounts that have `role`. `index` must be a - * value between 0 and {getRoleMemberCount}, non-inclusive. - * - * Role bearers are not sorted in any particular way, and their ordering may - * change at any point. - * - * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure - * you perform all queries on the same block. See the following - * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] - * for more information. - */ - function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { - return _roleMembers[role].at(index); - } - - /** - * @dev Returns the number of accounts that have `role`. Can be used - * together with {getRoleMember} to enumerate all bearers of a role. - */ - function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { - return _roleMembers[role].length(); - } - - /** - * @dev Overload {_grantRole} to track enumerable memberships - */ - function _grantRole(bytes32 role, address account) internal virtual override { - super._grantRole(role, account); - _roleMembers[role].add(account); - } - - /** - * @dev Overload {_revokeRole} to track enumerable memberships - */ - function _revokeRole(bytes32 role, address account) internal virtual override { - super._revokeRole(role, account); - _roleMembers[role].remove(account); - } -} - -// 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/v2/AccessController.sol -// License-Identifier: MIT - - -contract AccessController is AccessControlEnumerable, Pausable { - bytes32 public constant DAO_ADMIN_ROLE = keccak256("DAO_ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - bytes32 public constant CALLER_ROLE = keccak256("CALLER_ROLE"); - bytes32 public constant CALLEE_ROLE = keccak256("CALLEE_ROLE"); - - // access controller - // admin is helix Dao - modifier onlyAdmin() { - require(hasRole(DAO_ADMIN_ROLE, msg.sender), "AccessController:Bad admin role"); - _; - } - - // operator - modifier onlyOperator() { - require(hasRole(OPERATOR_ROLE, msg.sender), "AccessController:Bad operator role"); - _; - } - - modifier onlyCaller() { - require(hasRole(CALLER_ROLE, msg.sender), "AccessController:Bad caller role"); - _; - } - - modifier onlyCallee() { - require(hasRole(CALLEE_ROLE, msg.sender), "AccessController:Bad callee role"); - _; - } - - function _initialize(address admin) internal { - _setRoleAdmin(CALLER_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(CALLEE_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(OPERATOR_ROLE, DAO_ADMIN_ROLE); - _setRoleAdmin(DAO_ADMIN_ROLE, DAO_ADMIN_ROLE); - _setupRole(DAO_ADMIN_ROLE, admin); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } -} - -// File @zeppelin-solidity/contracts/access/Ownable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - -// File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @zeppelin-solidity/contracts/proxy/utils/Initializable.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), - "Initializable: contract is already initialized" - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, "Initializable: contract is initializing"); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// File contracts/mapping-token/v2/MappingTokenFactory.sol -// License-Identifier: MIT -// This is the Issuing Module(Mapping-token-factory) of the ethereum like bridge. -// We trust the inboundLane/outboundLane when we add them to the module. -// It means that each message from the inboundLane is verified correct and truthly from the sourceAccount. -// Only we need is to verify the sourceAccount is expected. And we add it to the Filter. - - - -contract MappingTokenFactory is AccessController, Initializable { - address[] public allMappingTokens; - // salt=>mappingToken, the salt is derived from origin token on backing chain - // so this is a mapping from origin to mapping token - mapping(bytes32 => address) public salt2MappingToken; - // mappingToken=>info the info is the original token info - // so this is a mapping from mappingToken to original token - mapping(address => address) public mappingToken2OriginalToken; - - address public messageEndpoint; - address public remoteBacking; - - uint256 internal locked; - modifier nonReentrant { - require(locked == 0, "MappingTokenFactory: locked"); - locked = 1; - _; - locked = 0; - } - - modifier onlyMessageEndpoint() { - require(messageEndpoint == msg.sender, "MappingTokenFactory:Bad message handle"); - _; - } - - function initialize(address _messageEndpoint) public initializer { - _setMessageEndpoint(_messageEndpoint); - _initialize(msg.sender); - } - - function _setMessageEndpoint(address _messageEndpoint) internal { - messageEndpoint = _messageEndpoint; - } - - function setRemoteBacking(address _remoteBacking) external onlyAdmin { - remoteBacking = _remoteBacking; - } - - function _transferMappingTokenOwnership(address mappingToken, address new_owner) internal { - Ownable(mappingToken).transferOwnership(new_owner); - } - - /** - * @notice add mapping-token address by owner - * @param salt the salt of the mapping token deployed - * @param originalToken the original token address - * @param mappingToken the mapping token address - */ - function _addMappingToken( - bytes32 salt, - address originalToken, - address mappingToken - ) internal { - // save the mapping tokens in an array so it can be listed - allMappingTokens.push(mappingToken); - // map the originToken to mappingInfo - salt2MappingToken[salt] = mappingToken; - // map the mappingToken to origin info - mappingToken2OriginalToken[mappingToken] = originalToken; - } - - // internal - function _deploy(bytes32 salt, bytes memory bytecodeWithInitdata) internal returns (address addr) { - assembly { - addr := create2(0, add(bytecodeWithInitdata, 0x20), mload(bytecodeWithInitdata), salt) - if iszero(extcodesize(addr)) { revert(0, 0) } - } - } - - function tokenLength() public view returns (uint) { - return allMappingTokens.length; - } - - function getMappingToken(address backingAddress, address originalToken) public view returns (address) { - bytes32 salt = keccak256(abi.encodePacked(backingAddress, originalToken)); - return salt2MappingToken[salt]; - } -} - -// 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) - - -// CAUTION -// This version of SafeMath should only be used with Solidity 0.8 or later, -// because it relies on the compiler's built in overflow checks. - -/** - * @dev Wrappers over Solidity's arithmetic operations. - * - * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler - * now has built in overflow checking. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - return a + b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - return a * b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b <= a, errorMessage); - return a - b; - } - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a / b; - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a % b; - } - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20.sol -// License-Identifier: MIT - - - -contract Erc20 is IERC20, Ownable { - using SafeMath for uint256; - - mapping (address => uint256) private _balances; - - mapping (address => mapping (address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string public name; - string public symbol; - uint8 public decimals; - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - _transferOwnership(_msgSender()); - } - - function totalSupply() public view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address account) public view override returns (uint256) { - return _balances[account]; - } - - function transfer(address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(msg.sender, recipient, amount); - return true; - } - - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _approve(msg.sender, spender, amount); - return true; - } - - function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(sender, recipient, amount); - _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")); - return true; - } - - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); - return true; - } - - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); - return true; - } - - function _transfer(address sender, address recipient, uint256 amount) internal virtual { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(sender, recipient, amount); - - _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); - _balances[recipient] = _balances[recipient].add(amount); - emit Transfer(sender, recipient, amount); - } - - // only factory contract can mint with the lock proof from ethereum - function mint(address account, uint256 amount) external onlyOwner { - _mint(account, amount); - } - - function burn(address account, uint256 amount) external { - if (account != msg.sender && owner() != msg.sender && _allowances[account][msg.sender] != type(uint256).max) { - _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: decreased allowance below zero")); - } - _burn(account, amount); - } - - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); - } - - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); - _totalSupply = _totalSupply.sub(amount); - emit Transfer(account, address(0), amount); - } - - function _approve(address owner, address spender, uint256 amount) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } -} - -// File @zeppelin-solidity/contracts/utils/structs/BitMaps.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol) - -/** - * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. - * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. - */ -library BitMaps { - struct BitMap { - mapping(uint256 => uint256) _data; - } - - /** - * @dev Returns whether the bit at `index` is set. - */ - function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - return bitmap._data[bucket] & mask != 0; - } - - /** - * @dev Sets the bit at `index` to the boolean `value`. - */ - function setTo( - BitMap storage bitmap, - uint256 index, - bool value - ) internal { - if (value) { - set(bitmap, index); - } else { - unset(bitmap, index); - } - } - - /** - * @dev Sets the bit at `index`. - */ - function set(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] |= mask; - } - - /** - * @dev Unsets the bit at `index`. - */ - function unset(BitMap storage bitmap, uint256 index) internal { - uint256 bucket = index >> 8; - uint256 mask = 1 << (index & 0xff); - bitmap._data[bucket] &= ~mask; - } -} - -// File contracts/mapping-token/v2/erc20-mapping-protocol/Erc20Sub2SubMappingTokenFactory.sol -// License-Identifier: MIT -// This is the Issuing Module(Mapping-token-factory) of the ethereum like bridge. -// We trust the inboundLane/outboundLane when we add them to the module. -// It means that each message from the inboundLane is verified correct and truthly from the sourceAccount. -// Only we need is to verify the sourceAccount is expected. And we add it to the Filter. - - - - - - - - - -contract Erc20Sub2SubMappingTokenFactory is DailyLimit, IErc20MappingTokenFactory, MappingTokenFactory { - struct BurnInfo { - bytes32 hash; - bool hasRefundForFailed; - } - - // guard - address public guard; - uint256 public helixFee; - - mapping(uint256 => BurnInfo) public burnMessages; - BitMaps.BitMap issueMessages; - address public xwToken; - - event NewLogicSetted(uint32 tokenType, address addr); - event IssuingERC20Created(address originalToken, address mappingToken); - event BurnAndRemoteUnlocked(uint256 transferId, bool isNative, bytes32 messageHash, address sender, address recipient, address token, uint256 amount, uint256 fee); - event TokenIssued(uint256 transferId, address token, address recipient, uint256 amount); - event TokenRemintForFailed(uint256 transferId, address token, address recipient, uint256 amount); - event RemoteUnlockFailure(uint256 refundId, uint256 transferId, uint256 fee); - - function setMessageEndpoint(address _messageEndpoint) external onlyAdmin { - _setMessageEndpoint(_messageEndpoint); - } - - function setMappingNativeWrappedToken(address _xwToken) external onlyAdmin { - xwToken = _xwToken; - } - - receive() external payable { - } - - /** - * @notice only admin can transfer the ownership of the mapping token from factory to other account - * generally we should not do this. When we encounter a non-recoverable error, we temporarily transfer the privileges to a maintenance account. - * @param mappingToken the address the mapping token - * @param new_owner the new owner of the mapping token - */ - function transferMappingTokenOwnership(address mappingToken, address new_owner) external onlyAdmin { - _transferMappingTokenOwnership(mappingToken, new_owner); - } - - function updateGuard(address newGuard) external onlyAdmin { - guard = newGuard; - } - - function changeDailyLimit(address mappingToken, uint amount) public onlyAdmin { - _changeDailyLimit(mappingToken, amount); - } - - function setHelixFee(uint256 _helixFee) external onlyAdmin { - helixFee = _helixFee; - } - - function fee() external view returns(uint256) { - return IHelixSub2SubMessageEndpoint(messageEndpoint).fee() + helixFee; - } - - function _sendMessage( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - bytes memory message - ) internal nonReentrant returns(uint256, uint256) { - uint256 bridgeFee = IHelixSub2SubMessageEndpoint(messageEndpoint).fee(); - uint256 totalFee = bridgeFee + helixFee; - require(msg.value >= totalFee, "MTF:the fee is not enough"); - if (msg.value > totalFee) { - // refund fee to msgSender - payable(msg.sender).transfer(msg.value - totalFee); - } - uint256 transferId = IHelixSub2SubMessageEndpoint(messageEndpoint).sendMessage{value: bridgeFee}( - remoteSpecVersion, - remoteReceiveGasLimit, - remoteBacking, - message); - return (transferId, totalFee); - } - - /** - * @notice create new erc20 mapping contract, this can only be called by inboundLane - * @param originalToken the original token address - * @param name the name of the original erc20 token - * @param symbol the symbol of the original erc20 token - * @param decimals the decimals of the original erc20 token - */ - function newErc20Contract( - address originalToken, - string memory bridgedChainName, - string memory name, - string memory symbol, - uint8 decimals, - uint256 dailyLimit - ) public onlyMessageEndpoint whenNotPaused returns (address mappingToken) { - bytes32 salt = keccak256(abi.encodePacked(remoteBacking, originalToken)); - require(salt2MappingToken[salt] == address(0), "MTF:contract has been deployed"); - - bytes memory bytecode = type(Erc20).creationCode; - bytes memory bytecodeWithInitdata = abi.encodePacked( - bytecode, - abi.encode( - string(abi.encodePacked(name, "[", bridgedChainName, ">")), - string(abi.encodePacked("x", symbol)), - decimals - )); - mappingToken = _deploy(salt, bytecodeWithInitdata); - _addMappingToken(salt, originalToken, mappingToken); - _changeDailyLimit(mappingToken, dailyLimit); - emit IssuingERC20Created(originalToken, mappingToken); - } - - /** - * @notice issue mapping token, only can be called by inboundLane - * @param originalToken the original token address - * @param recipient the recipient of the issued mapping token - * @param amount the amount of the issued mapping token - */ - function issueMappingToken( - address originalToken, - address recipient, - uint256 amount - ) public onlyMessageEndpoint whenNotPaused { - address mappingToken = getMappingToken(remoteBacking, originalToken); - require(mappingToken != address(0), "MTF:mapping token has not created"); - require(amount > 0, "MTF:can not receive amount zero"); - expendDailyLimit(mappingToken, amount); - uint256 transferId = IHelixSub2SubMessageEndpoint(messageEndpoint).lastDeliveredMessageId() + 1; - require(BitMaps.get(issueMessages, transferId) == false, "MTF:message has been accepted"); - BitMaps.set(issueMessages, transferId); - if (guard != address(0)) { - Erc20(mappingToken).mint(address(this), amount); - uint allowance = IERC20(mappingToken).allowance(address(this), guard); - require(IERC20(mappingToken).approve(guard, allowance + amount), "MTF:approve token transfer to guard failed"); - IGuard(guard).deposit(transferId, mappingToken, recipient, amount); - } else { - Erc20(mappingToken).mint(recipient, amount); - } - emit TokenIssued(transferId, mappingToken, recipient, amount); - } - - /** - * @notice burn mapping token and unlock remote original token - * @param mappingToken the burt mapping token address - * @param recipient the recipient of the remote unlocked token - * @param amount the amount of the burn and unlock - */ - function _burnAndRemoteUnlock( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address mappingToken, - address recipient, - uint256 amount, - bytes memory remoteUnlockCall, - bool isNative - ) internal { - require(amount > 0, "MTF:can not transfer amount zero"); - // transfer to this and then burn - require(IERC20(mappingToken).transferFrom(msg.sender, address(this), amount), "MTF:transfer token failed"); - Erc20(mappingToken).burn(address(this), amount); - - (uint256 transferId, uint256 totalFee) = _sendMessage( - remoteSpecVersion, - remoteReceiveGasLimit, - remoteUnlockCall - ); - require(burnMessages[transferId].hash == bytes32(0), "MTF: message exist"); - bytes32 messageHash = hash(abi.encodePacked(transferId, mappingToken, msg.sender, amount)); - burnMessages[transferId] = BurnInfo(messageHash, false); - emit BurnAndRemoteUnlocked(transferId, isNative, messageHash, msg.sender, recipient, mappingToken, amount, totalFee); - } - - /** - * @notice burn mapping token and unlock remote original token - * @param mappingToken the burt mapping token address - * @param recipient the recipient of the remote unlocked token - * @param amount the amount of the burn and unlock - */ - function burnAndRemoteUnlock( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address mappingToken, - address recipient, - uint256 amount - ) external payable whenNotPaused { - address originalToken = mappingToken2OriginalToken[mappingToken]; - require(originalToken != address(0), "MTF:token is not created by factory"); - bytes memory unlockFromRemote = abi.encodeWithSelector( - IBacking.unlockFromRemote.selector, - originalToken, - recipient, - amount - ); - _burnAndRemoteUnlock( - remoteSpecVersion, - remoteReceiveGasLimit, - mappingToken, - recipient, - amount, - unlockFromRemote, - false - ); - } - - function burnAndRemoteUnlockNative( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - address recipient, - uint256 amount - ) external payable whenNotPaused { - require(amount > 0, "MTF:can not transfer amount zero"); - address originalToken = mappingToken2OriginalToken[xwToken]; - require(originalToken != address(0), "MTF:token is not created by factory"); - bytes memory unlockFromRemoteNative = abi.encodeWithSelector( - IBackingSupportNative.unlockFromRemoteNative.selector, - recipient, - amount - ); - _burnAndRemoteUnlock( - remoteSpecVersion, - remoteReceiveGasLimit, - xwToken, - recipient, - amount, - unlockFromRemoteNative, - true); - } - - /** - * @notice send a unlock message to backing when issue mapping token faild to redeem original token. - * @param originalToken the original token address - * @param originalSender the originalSender of the remote unlocked token, must be the same as msg.send of the failed message. - * @param amount the amount of the failed issue token. - */ - function remoteUnlockFailure( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - uint256 transferId, - address originalToken, - address originalSender, - uint256 amount - ) external payable whenNotPaused { - // must not exist in successful issue list - require(BitMaps.get(issueMessages, transferId) == false, "MTF:success message can't refund for failed"); - // must has been checked by message layer - bool messageChecked = IHelixSub2SubMessageEndpoint(messageEndpoint).isMessageDelivered(transferId); - require(messageChecked, "MTF:the message is not checked by message layer"); - bytes memory handleUnlockForFailed = abi.encodeWithSelector( - IHelixAppSupportWithdrawFailed.handleUnlockFailureFromRemote.selector, - transferId, - originalToken, - originalSender, - amount - ); - (uint256 refundId, uint256 totalFee) = _sendMessage( - remoteSpecVersion, - remoteReceiveGasLimit, - handleUnlockForFailed - ); - emit RemoteUnlockFailure(refundId, transferId, totalFee); - } - - /** - * @notice send a unlock message to backing when issue mapping token faild to redeem original token. - * @param originalSender the originalSender of the remote unlocked token, must be the same as msg.send of the failed message. - * @param amount the amount of the failed issue token. - */ - function remoteUnlockFailureNative( - uint32 remoteSpecVersion, - uint256 remoteReceiveGasLimit, - uint256 transferId, - address originalSender, - uint256 amount - ) external payable whenNotPaused { - // must not exist in successful issue list - require(BitMaps.get(issueMessages, transferId) == false, "MTF:success message can't refund for failed"); - // must has been checked by message layer - bool messageChecked = IHelixSub2SubMessageEndpoint(messageEndpoint).isMessageDelivered(transferId); - require(messageChecked, "MTF:the message is not checked by message layer"); - bytes memory handleUnlockForFailed = abi.encodeWithSelector( - IHelixAppSupportWithdrawFailed.handleUnlockFailureFromRemoteNative.selector, - transferId, - originalSender, - amount - ); - (uint256 refundId, uint256 totalFee) = _sendMessage( - remoteSpecVersion, - remoteReceiveGasLimit, - handleUnlockForFailed - ); - emit RemoteUnlockFailure(refundId, transferId, totalFee); - } - - /** - * @notice this will be called by messageEndpoint when the remote backing unlock failed and want to unlock the mapping token - * @param token the original token address - * @param origin_sender the origin_sender who will receive the unlocked token - * @param amount amount of the unlocked token - */ - function handleIssuingFailureFromRemote( - uint256 transferId, - address token, - address origin_sender, - uint256 amount - ) external onlyMessageEndpoint whenNotPaused { - BurnInfo memory burnInfo = burnMessages[transferId]; - require(burnInfo.hasRefundForFailed == false, "MTF:the burn message has been refund"); - bytes32 messageHash = hash(abi.encodePacked(transferId, token, origin_sender, amount)); - require(burnInfo.hash == messageHash, "MTF:message is not matched"); - burnMessages[transferId].hasRefundForFailed = true; - // remint token - Erc20(token).mint(origin_sender, amount); - emit TokenRemintForFailed(transferId, token, origin_sender, amount); - } - - function hash(bytes memory value) public pure returns (bytes32) { - return sha256(value); - } - - function rescueFunds( - address token, - address recipient, - uint256 amount - ) external onlyAdmin { - IERC20(token).transfer(recipient, amount); - } - - function withdrawFee( - address payable recipient, - uint256 amount - ) external onlyAdmin { - recipient.transfer(amount); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2sub/Guard.sol b/helix-contract/flatten/sub2sub/Guard.sol deleted file mode 100644 index 95995d8f..00000000 --- a/helix-contract/flatten/sub2sub/Guard.sol +++ /dev/null @@ -1,1207 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 4/28/2023 - **/ - -pragma solidity ^0.8.10; - -// 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) - - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} - -// File @zeppelin-solidity/contracts/utils/cryptography/ECDSA.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) - - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - enum RecoverError { - NoError, - InvalidSignature, - InvalidSignatureLength, - InvalidSignatureS, - InvalidSignatureV - } - - function _throwError(RecoverError error) private pure { - if (error == RecoverError.NoError) { - return; // no error: do nothing - } else if (error == RecoverError.InvalidSignature) { - revert("ECDSA: invalid signature"); - } else if (error == RecoverError.InvalidSignatureLength) { - revert("ECDSA: invalid signature length"); - } else if (error == RecoverError.InvalidSignatureS) { - revert("ECDSA: invalid signature 's' value"); - } else if (error == RecoverError.InvalidSignatureV) { - revert("ECDSA: invalid signature 'v' value"); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature` or error string. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - * - * Documentation for signature generation: - * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] - * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] - * - * _Available since v4.3._ - */ - function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { - if (signature.length == 65) { - bytes32 r; - bytes32 s; - uint8 v; - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - /// @solidity memory-safe-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - return tryRecover(hash, v, r, s); - } else { - return (address(0), RecoverError.InvalidSignatureLength); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - */ - function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, signature); - _throwError(error); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. - * - * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] - * - * _Available since v4.3._ - */ - function tryRecover( - bytes32 hash, - bytes32 r, - bytes32 vs - ) internal pure returns (address, RecoverError) { - bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); - uint8 v = uint8((uint256(vs) >> 255) + 27); - return tryRecover(hash, v, r, s); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. - * - * _Available since v4.2._ - */ - function recover( - bytes32 hash, - bytes32 r, - bytes32 vs - ) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, r, vs); - _throwError(error); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `v`, - * `r` and `s` signature fields separately. - * - * _Available since v4.3._ - */ - function tryRecover( - bytes32 hash, - uint8 v, - bytes32 r, - bytes32 s - ) internal pure returns (address, RecoverError) { - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { - return (address(0), RecoverError.InvalidSignatureS); - } - if (v != 27 && v != 28) { - return (address(0), RecoverError.InvalidSignatureV); - } - - // If the signature is valid (and not malleable), return the signer address - address signer = ecrecover(hash, v, r, s); - if (signer == address(0)) { - return (address(0), RecoverError.InvalidSignature); - } - - return (signer, RecoverError.NoError); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `v`, - * `r` and `s` signature fields separately. - */ - function recover( - bytes32 hash, - uint8 v, - bytes32 r, - bytes32 s - ) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, v, r, s); - _throwError(error); - return recovered; - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * produces hash corresponding to the one signed with the - * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] - * JSON-RPC method as part of EIP-191. - * - * See {recover}. - */ - function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } - - /** - * @dev Returns an Ethereum Signed Message, created from `s`. This - * produces hash corresponding to the one signed with the - * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] - * JSON-RPC method as part of EIP-191. - * - * See {recover}. - */ - function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); - } - - /** - * @dev Returns an Ethereum Signed Typed Data, created from a - * `domainSeparator` and a `structHash`. This produces hash corresponding - * to the one signed with the - * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] - * JSON-RPC method as part of EIP-712. - * - * See {recover}. - */ - function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); - } -} - -// File contracts/mapping-token/v2/GuardRegistry.sol -// License-Identifier: Apache-2.0 - -pragma experimental ABIEncoderV2; - -/** - * @title Manages a set of guards and a threshold to double-check BEEFY commitment - * @dev Stores the guards and a threshold - * @author echo - */ -contract GuardRegistry { - event AddedGuard(address guard); - event RemovedGuard(address guard); - event ChangedThreshold(uint256 threshold); - - // keccak256( - // "EIP712Domain(uint256 chainId,address verifyingContract)" - // ); - bytes32 internal constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; - - address internal constant SENTINEL_GUARDS = address(0x1); - - /** - * @dev Nonce to prevent replay of update operations - */ - uint256 public nonce; - /** - * @dev Store all guards in the linked list - */ - mapping(address => address) internal guards; - /** - * @dev Count of all guards - */ - uint256 internal guardCount; - /** - * @dev Number of required confirmations for update operations - */ - uint256 internal threshold; - - /** - * @dev Sets initial storage of contract. - * @param _guards List of Safe guards. - * @param _threshold Number of required confirmations for check commitment or change guards. - */ - function initialize(address[] memory _guards, uint256 _threshold) internal { - // Threshold can only be 0 at initialization. - // Check ensures that setup function can only be called once. - require(threshold == 0, "Guard: Guards have already been setup"); - // Validate that threshold is smaller than number of added guards. - require(_threshold <= _guards.length, "Guard: Threshold cannot exceed guard count"); - // There has to be at least one Safe guard. - require(_threshold >= 1, "Guard: Threshold needs to be greater than 0"); - // Initializing Safe guards. - address currentGuard = SENTINEL_GUARDS; - for (uint256 i = 0; i < _guards.length; i++) { - // Guard address cannot be null. - address guard = _guards[i]; - require(guard != address(0) && guard != SENTINEL_GUARDS && guard != address(this) && currentGuard != guard, "Guard: Invalid guard address provided"); - // No duplicate guards allowed. - require(guards[guard] == address(0), "Guard: Address is already an guard"); - guards[currentGuard] = guard; - currentGuard = guard; - emit AddedGuard(guard); - } - guards[currentGuard] = SENTINEL_GUARDS; - guardCount = _guards.length; - threshold = _threshold; - } - - /** - * @dev Allows to add a new guard to the registry and update the threshold at the same time. - * This can only be done via multi-sig. - * @notice Adds the guard `guard` to the registry and updates the threshold to `_threshold`. - * @param guard New guard address. - * @param _threshold New threshold. - * @param signatures The signatures of the guards which to add new guard and update the `threshold` . - */ - function addGuardWithThreshold( - address guard, - uint256 _threshold, - bytes[] memory signatures - ) public { - // Guard address cannot be null, the sentinel or the registry itself. - require(guard != address(0) && guard != SENTINEL_GUARDS && guard != address(this), "Guard: Invalid guard address provided"); - // No duplicate guards allowed. - require(guards[guard] == address(0), "Guard: Address is already an guard"); - verifyGuardSignatures(msg.sig, abi.encode(guard, _threshold), signatures); - guards[guard] = guards[SENTINEL_GUARDS]; - guards[SENTINEL_GUARDS] = guard; - guardCount++; - emit AddedGuard(guard); - // Change threshold if threshold was changed. - if (threshold != _threshold) _changeThreshold(_threshold); - } - - /** - * @dev Allows to remove an guard from the registry and update the threshold at the same time. - * This can only be done via multi-sig. - * @notice Removes the guard `guard` from the registry and updates the threshold to `_threshold`. - * @param prevGuard Guard that pointed to the guard to be removed in the linked list - * @param guard Guard address to be removed. - * @param _threshold New threshold. - * @param signatures The signatures of the guards which to remove a guard and update the `threshold` . - */ - function removeGuard( - address prevGuard, - address guard, - uint256 _threshold, - bytes[] memory signatures - ) public { - // Only allow to remove an guard, if threshold can still be reached. - require(guardCount - 1 >= _threshold, "Guard: Threshold cannot exceed guard count"); - // Validate guard address and check that it corresponds to guard index. - require(guard != address(0) && guard != SENTINEL_GUARDS, "Guard: Invalid guard address provided"); - require(guards[prevGuard] == guard, "Guard: Invalid prevGuard, guard pair provided"); - verifyGuardSignatures(msg.sig, abi.encode(prevGuard, guard, _threshold), signatures); - guards[prevGuard] = guards[guard]; - guards[guard] = address(0); - guardCount--; - emit RemovedGuard(guard); - // Change threshold if threshold was changed. - if (threshold != _threshold) _changeThreshold(_threshold); - } - - /** - * @dev Allows to swap/replace a guard from the registry with another address. - * This can only be done via multi-sig. - * @notice Replaces the guard `oldGuard` in the registry with `newGuard`. - * @param prevGuard guard that pointed to the guard to be replaced in the linked list - * @param oldGuard guard address to be replaced. - * @param newGuard New guard address. - * @param signatures The signatures of the guards which to swap/replace a guard and update the `threshold` . - */ - function swapGuard( - address prevGuard, - address oldGuard, - address newGuard, - bytes[] memory signatures - ) public { - // Guard address cannot be null, the sentinel or the registry itself. - require(newGuard != address(0) && newGuard != SENTINEL_GUARDS && newGuard != address(this), "Guard: Invalid guard address provided"); - // No duplicate guards allowed. - require(guards[newGuard] == address(0), "Guard: Address is already an guard"); - // Validate oldGuard address and check that it corresponds to guard index. - require(oldGuard != address(0) && oldGuard != SENTINEL_GUARDS, "Guard: Invalid guard address provided"); - require(guards[prevGuard] == oldGuard, "Guard: Invalid prevGuard, guard pair provided"); - verifyGuardSignatures(msg.sig, abi.encode(prevGuard, oldGuard, newGuard), signatures); - guards[newGuard] = guards[oldGuard]; - guards[prevGuard] = newGuard; - guards[oldGuard] = address(0); - emit RemovedGuard(oldGuard); - emit AddedGuard(newGuard); - } - - /** - * @dev Allows to update the number of required confirmations by guards. - * This can only be done via multi-sig. - * @notice Changes the threshold of the registry to `_threshold`. - * @param _threshold New threshold. - * @param signatures The signatures of the guards which to update the `threshold` . - */ - function changeThreshold(uint256 _threshold, bytes[] memory signatures) public { - verifyGuardSignatures(msg.sig, abi.encode(_threshold), signatures); - _changeThreshold(_threshold); - } - - function _changeThreshold(uint256 _threshold) internal { - // Validate that threshold is smaller than number of owners. - require(_threshold <= guardCount, "Guard: Threshold cannot exceed guard count"); - // There has to be at least one guard. - require(_threshold >= 1, "Guard: Threshold needs to be greater than 0"); - threshold = _threshold; - emit ChangedThreshold(threshold); - } - - function getThreshold() public view returns (uint256) { - return threshold; - } - - function isGuard(address guard) public view returns (bool) { - return guard != SENTINEL_GUARDS && guards[guard] != address(0); - } - - /** - * @dev Returns array of guards. - * @return Array of guards. - */ - function getGuards() public view returns (address[] memory) { - address[] memory array = new address[](guardCount); - - // populate return array - uint256 index = 0; - address currentGuard = guards[SENTINEL_GUARDS]; - while (currentGuard != SENTINEL_GUARDS) { - array[index] = currentGuard; - currentGuard = guards[currentGuard]; - index++; - } - return array; - } - - function verifyGuardSignatures( - bytes4 methodID, - bytes memory params, - bytes[] memory signatures - ) internal { - bytes32 structHash = - keccak256( - abi.encode( - methodID, - params, - nonce - ) - ); - checkGuardSignatures(structHash, signatures); - nonce++; - } - - function verifyGuardSignaturesWithoutNonce( - bytes4 methodID, - bytes memory params, - bytes[] memory signatures - ) view internal { - bytes32 structHash = - keccak256( - abi.encode( - methodID, - params - ) - ); - checkGuardSignatures(structHash, signatures); - } - - /** - * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise. - * @param structHash The struct Hash of the data (could be either a message/commitment hash). - * @param signatures Signature data that should be verified. only ECDSA signature. - * Signers need to be sorted in ascending order - */ - function checkGuardSignatures( - bytes32 structHash, - bytes[] memory signatures - ) public view { - // Load threshold to avoid multiple storage loads - uint256 _threshold = threshold; - // Check that a threshold is set - require(_threshold > 0, "Guard: Threshold needs to be defined"); - bytes32 dataHash = encodeDataHash(structHash); - checkNSignatures(dataHash, signatures, _threshold); - } - - /** - * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise. - * @param dataHash Hash of the data (could be either a message hash or transaction hash). - * @param signatures Signature data that should be verified. only ECDSA signature. - * Signers need to be sorted in ascending order - * @param requiredSignatures Amount of required valid signatures. - */ - function checkNSignatures( - bytes32 dataHash, - bytes[] memory signatures, - uint256 requiredSignatures - ) public view { - // Check that the provided signature data is not too short - require(signatures.length >= requiredSignatures, "GS020"); - // There cannot be an owner with address 0. - address lastGuard = address(0); - address currentGuard; - for (uint256 i = 0; i < requiredSignatures; i++) { - currentGuard = ECDSA.recover(dataHash, signatures[i]); - require(currentGuard > lastGuard && guards[currentGuard] != address(0) && currentGuard != SENTINEL_GUARDS, "Guard: Invalid guard provided"); - lastGuard = currentGuard; - } - } - - /** - * @dev Returns the chain id used by this contract. - */ - function getChainId() public view returns (uint256) { - uint256 id; - // solhint-disable-next-line no-inline-assembly - assembly { - id := chainid() - } - return id; - } - - function domainSeparator() public view returns (bytes32) { - return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), address(this))); - } - - function encodeDataHash(bytes32 structHash) public view returns (bytes32) { - return keccak256(abi.encodePacked(hex"1901", domainSeparator(), structHash)); - } -} - -// 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 @zeppelin-solidity/contracts/utils/math/SafeMath.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) - - -// CAUTION -// This version of SafeMath should only be used with Solidity 0.8 or later, -// because it relies on the compiler's built in overflow checks. - -/** - * @dev Wrappers over Solidity's arithmetic operations. - * - * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler - * now has built in overflow checking. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - return a + b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - return a * b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b <= a, errorMessage); - return a - b; - } - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a / b; - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - unchecked { - require(b > 0, errorMessage); - return a % b; - } - } -} - -// 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/mapping-token/v2/Guard.sol -// License-Identifier: Apache-2.0 - - - - - - -contract Guard is GuardRegistry, Pausable { - using SafeMath for uint256; - - mapping(uint256 => bytes32) depositors; - - uint256 public maxUnclaimableTime; - address public depositor; - address public operator; - - event TokenDeposit(uint256 id, address token, address recipient, uint256 amount); - event TokenClaimed(uint256 id); - - constructor(address[] memory _guards, uint256 _threshold, uint256 _maxUnclaimableTime, address _depositor) { - maxUnclaimableTime = _maxUnclaimableTime; - depositor = _depositor; - operator = msg.sender; - initialize(_guards, _threshold); - } - - modifier onlyDepositor() { - require(msg.sender == depositor, "Guard: Invalid depositor"); - _; - } - - modifier onlyOperator() { - require(msg.sender == operator, "Guard: Invalid operator"); - _; - } - - function unpause() external onlyOperator { - _unpause(); - } - - function pause() external onlyOperator { - _pause(); - } - - function setOperator(address newOperator, bytes[] memory signatures) external { - verifyGuardSignatures(msg.sig, abi.encode(newOperator), signatures); - operator = newOperator; - } - - function setMaxUnclaimableTime(uint256 _maxUnclaimableTime) external onlyOperator { - maxUnclaimableTime = _maxUnclaimableTime; - } - - /** - * @dev deposit token to guard, waiting to claim, only allowed depositor - * @param id the id of the operation, should be siged later by guards - * @param token the erc20 token address - * @param recipient the recipient of the token - * @param amount the amount of the token - */ - function deposit( - uint256 id, - address token, - address recipient, - uint256 amount - ) public onlyDepositor whenNotPaused { - depositors[id] = hash(abi.encodePacked(block.timestamp, token, recipient, amount)); - emit TokenDeposit(id, token, recipient, amount); - } - - function claimById( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bool isNative - ) internal { - require(hash(abi.encodePacked(timestamp, token, recipient, amount)) == depositors[id], "Guard: Invalid id to claim"); - require(amount > 0, "Guard: Invalid amount to claim"); - if (isNative) { - require(IERC20(token).transferFrom(depositor, address(this), amount), "Guard: claim native token failed"); - 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); - } else { - require(IERC20(token).transferFrom(depositor, recipient, amount), "Guard: claim token failed"); - } - delete depositors[id]; - emit TokenClaimed(id); - } - - /** - * @dev claim the tokens in the contract saved by deposit, this acquire signatures from guards - * @param id the id to be claimed - * @param signatures the signatures of the guards which to claim tokens. - */ - function claim( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bytes[] memory signatures - ) public { - verifyGuardSignaturesWithoutNonce(msg.sig, abi.encode(id, timestamp, token, recipient, amount), signatures); - claimById(id, timestamp, token, recipient, amount, false); - } - - /** - * @dev claimNative the tokens in the contract saved by deposit, this acquire signatures from guards - * @param id the id to be claimed - * @param signatures the signatures of the guards which to claim tokens. - */ - function claimNative( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bytes[] memory signatures - ) public { - verifyGuardSignaturesWithoutNonce(msg.sig, abi.encode(id, timestamp, token, recipient, amount), signatures); - claimById(id, timestamp, token, recipient, amount, true); - } - - /** - * @dev claim the tokens without signatures, this only allowed when timeout - * @param id the id to be claimed - */ - function claimByTimeout( - uint256 id, - uint256 timestamp, - address token, - address recipient, - uint256 amount, - bool isNative - ) public whenNotPaused { - require(timestamp < block.timestamp && block.timestamp - timestamp > maxUnclaimableTime, "Guard: claim at invalid time"); - claimById(id, timestamp, token, recipient, amount, isNative); - } - - function hash(bytes memory value) public pure returns (bytes32) { - return sha256(value); - } -} \ No newline at end of file diff --git a/helix-contract/flatten/sub2sub/WToken.sol b/helix-contract/flatten/sub2sub/WToken.sol deleted file mode 100644 index 304a75a8..00000000 --- a/helix-contract/flatten/sub2sub/WToken.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - * .----------------. .----------------. .----------------. .----------------. .----------------. - * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | - * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | - * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | - * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | - * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | - * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | - * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | - * | | | || | | || | | || | | || | | | - * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | - * '----------------' '----------------' '----------------' '----------------' '----------------' ' - * - * - * 4/28/2023 - **/ - -pragma solidity ^0.8.10; - -// File contracts/mapping-token/v2/erc20-mapping-protocol/WToken.sol -// License-Identifier: MIT - - -contract WToken { - string public name; - string public symbol; - uint8 public decimals; - - event Approval(address indexed src, address indexed guy, uint wad); - event Transfer(address indexed src, address indexed dst, uint wad); - event Deposit(address indexed dst, uint wad); - event Withdrawal(address indexed src, uint wad); - - mapping (address => uint) public balanceOf; - mapping (address => mapping (address => uint)) public allowance; - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - } - - receive() external payable { - deposit(); - } - - function deposit() public payable { - balanceOf[msg.sender] += msg.value; - emit Deposit(msg.sender, msg.value); - } - function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - payable(msg.sender).transfer(wad); - emit Withdrawal(msg.sender, wad); - } - - function totalSupply() public view returns (uint) { - return address(this).balance; - } - - function approve(address guy, uint wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - emit Approval(msg.sender, guy, wad); - return true; - } - - function transfer(address dst, uint wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint wad) - public - returns (bool) - { - require(balanceOf[src] >= wad); - - if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - emit Transfer(src, dst, wad); - - return true; - } -} \ No newline at end of file diff --git a/helix-contract/hardhat.config.js b/helix-contract/hardhat.config.js index ccc9e2ef..4dc1be5c 100644 --- a/helix-contract/hardhat.config.js +++ b/helix-contract/hardhat.config.js @@ -162,7 +162,7 @@ subtask("flat:get-flattened-sources", "Returns all contracts and their dependenc flattened = flattened.replace(/SPDX-License-Identifier:/gm, "License-Identifier:") flattened = flattened.replace(/pragma solidity [\^>=0-9.]*;\n/gm, "") - flattened = `pragma solidity ^0.8.10;\n\n${flattened}` + flattened = `pragma solidity ^0.8.17;\n\n${flattened}` flattened = `/** * .----------------. .----------------. .----------------. .----------------. .----------------. * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |