From 2134853e55df2322abd5836dc2d6938883d9481b Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 8 May 2024 13:56:01 +0300 Subject: [PATCH 01/13] omnichain swap to zeta --- omnichain/swap/contracts/Swap.sol | 71 +++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/omnichain/swap/contracts/Swap.sol b/omnichain/swap/contracts/Swap.sol index 4e2152c8..847bfb78 100644 --- a/omnichain/swap/contracts/Swap.sol +++ b/omnichain/swap/contracts/Swap.sol @@ -5,13 +5,21 @@ import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract Swap is zContract { - SystemContract public immutable systemContract; + SystemContract public systemContract; + address public wzeta; + address public factory; + address public router; + uint256 constant BITCOIN = 18332; constructor(address systemContractAddress) { systemContract = SystemContract(systemContractAddress); + wzeta = systemContract.wZetaContractAddress(); + factory = systemContract.uniswapv2FactoryAddress(); + router = systemContract.uniswapv2Router02Address(); } modifier onlySystem() { @@ -45,30 +53,47 @@ contract Swap is zContract { recipientAddress = recipient; } - (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) - .withdrawGasFee(); + if (targetTokenAddress == wzeta) { + uint256 outputAmount = SwapHelperLib._doSwap( + wzeta, + factory, + router, + zrc20, + amount, + wzeta, + 0 + ); - uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), - zrc20, - gasFee, - gasZRC20, - amount - ); + IERC20(wzeta).transfer( + address(uint160(bytes20(recipientAddress))), + outputAmount + ); + } else { + (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) + .withdrawGasFee(); - uint256 outputAmount = SwapHelperLib._doSwap( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), - zrc20, - amount - inputForGas, - targetTokenAddress, - 0 - ); + uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( + wzeta, + factory, + router, + zrc20, + gasFee, + gasZRC20, + amount + ); - IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); - IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + uint256 outputAmount = SwapHelperLib._doSwap( + wzeta, + factory, + router, + zrc20, + amount - inputForGas, + targetTokenAddress, + 0 + ); + + IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); + IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + } } } From 2b304b211cdfeaddbf643dc77c8470f6091e8d69 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 8 May 2024 15:16:16 +0300 Subject: [PATCH 02/13] simplify --- omnichain/swap/contracts/Swap.sol | 45 +++++++++++++------------------ 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/omnichain/swap/contracts/Swap.sol b/omnichain/swap/contracts/Swap.sol index 847bfb78..56b51e35 100644 --- a/omnichain/swap/contracts/Swap.sol +++ b/omnichain/swap/contracts/Swap.sol @@ -53,26 +53,15 @@ contract Swap is zContract { recipientAddress = recipient; } - if (targetTokenAddress == wzeta) { - uint256 outputAmount = SwapHelperLib._doSwap( - wzeta, - factory, - router, - zrc20, - amount, - wzeta, - 0 - ); + bool isTargetZeta = targetTokenAddress == wzeta; + uint256 inputForGas; + address gasZRC20; + uint256 gasFee; - IERC20(wzeta).transfer( - address(uint160(bytes20(recipientAddress))), - outputAmount - ); - } else { - (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) - .withdrawGasFee(); + if (!isTargetZeta) { + (gasZRC20, gasFee) = IZRC20(targetTokenAddress).withdrawGasFee(); - uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( + inputForGas = SwapHelperLib.swapTokensForExactTokens( wzeta, factory, router, @@ -81,17 +70,19 @@ contract Swap is zContract { gasZRC20, amount ); + } - uint256 outputAmount = SwapHelperLib._doSwap( - wzeta, - factory, - router, - zrc20, - amount - inputForGas, - targetTokenAddress, - 0 - ); + uint256 outputAmount = SwapHelperLib._doSwap( + wzeta, + factory, + router, + zrc20, + isTargetZeta ? amount : amount - inputForGas, + targetTokenAddress, + 0 + ); + if (!isTargetZeta) { IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); } From c5cf646460d0c8dc4b1c5d4239a08d1fa75d9ba3 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 8 May 2024 16:47:32 +0300 Subject: [PATCH 03/13] add swap back --- omnichain/swap/contracts/Swap.sol | 52 +- omnichain/swap/contracts/SwapExtended.sol | 90 + omnichain/swap/flat | 2453 +++++++++++++++++++++ omnichain/swap/tasks/deploy.ts | 9 +- 4 files changed, 2565 insertions(+), 39 deletions(-) create mode 100644 omnichain/swap/contracts/SwapExtended.sol create mode 100644 omnichain/swap/flat diff --git a/omnichain/swap/contracts/Swap.sol b/omnichain/swap/contracts/Swap.sol index 56b51e35..4e2152c8 100644 --- a/omnichain/swap/contracts/Swap.sol +++ b/omnichain/swap/contracts/Swap.sol @@ -5,21 +5,13 @@ import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract Swap is zContract { - SystemContract public systemContract; - address public wzeta; - address public factory; - address public router; - + SystemContract public immutable systemContract; uint256 constant BITCOIN = 18332; constructor(address systemContractAddress) { systemContract = SystemContract(systemContractAddress); - wzeta = systemContract.wZetaContractAddress(); - factory = systemContract.uniswapv2FactoryAddress(); - router = systemContract.uniswapv2Router02Address(); } modifier onlySystem() { @@ -53,38 +45,30 @@ contract Swap is zContract { recipientAddress = recipient; } - bool isTargetZeta = targetTokenAddress == wzeta; - uint256 inputForGas; - address gasZRC20; - uint256 gasFee; - - if (!isTargetZeta) { - (gasZRC20, gasFee) = IZRC20(targetTokenAddress).withdrawGasFee(); + (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) + .withdrawGasFee(); - inputForGas = SwapHelperLib.swapTokensForExactTokens( - wzeta, - factory, - router, - zrc20, - gasFee, - gasZRC20, - amount - ); - } + uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( + systemContract.wZetaContractAddress(), + systemContract.uniswapv2FactoryAddress(), + systemContract.uniswapv2Router02Address(), + zrc20, + gasFee, + gasZRC20, + amount + ); uint256 outputAmount = SwapHelperLib._doSwap( - wzeta, - factory, - router, + systemContract.wZetaContractAddress(), + systemContract.uniswapv2FactoryAddress(), + systemContract.uniswapv2Router02Address(), zrc20, - isTargetZeta ? amount : amount - inputForGas, + amount - inputForGas, targetTokenAddress, 0 ); - if (!isTargetZeta) { - IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); - IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); - } + IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); + IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); } } diff --git a/omnichain/swap/contracts/SwapExtended.sol b/omnichain/swap/contracts/SwapExtended.sol new file mode 100644 index 00000000..f919e774 --- /dev/null +++ b/omnichain/swap/contracts/SwapExtended.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.7; + +import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; +import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; +import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; +import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract SwapExtended is zContract { + SystemContract public systemContract; + address public wzeta; + address public factory; + address public router; + + uint256 constant BITCOIN = 18332; + + constructor(address systemContractAddress) { + systemContract = SystemContract(systemContractAddress); + wzeta = systemContract.wZetaContractAddress(); + factory = systemContract.uniswapv2FactoryAddress(); + router = systemContract.uniswapv2Router02Address(); + } + + modifier onlySystem() { + require( + msg.sender == address(systemContract), + "Only system contract can call this function" + ); + _; + } + + function onCrossChainCall( + zContext calldata context, + address zrc20, + uint256 amount, + bytes calldata message + ) external virtual override onlySystem { + address targetTokenAddress; + bytes memory recipientAddress; + + if (context.chainID == BITCOIN) { + targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); + recipientAddress = abi.encodePacked( + BytesHelperLib.bytesToAddress(message, 20) + ); + } else { + (address targetToken, bytes memory recipient) = abi.decode( + message, + (address, bytes) + ); + targetTokenAddress = targetToken; + recipientAddress = recipient; + } + + bool isTargetZeta = targetTokenAddress == wzeta; + uint256 inputForGas; + address gasZRC20; + uint256 gasFee; + + if (!isTargetZeta) { + (gasZRC20, gasFee) = IZRC20(targetTokenAddress).withdrawGasFee(); + + inputForGas = SwapHelperLib.swapTokensForExactTokens( + wzeta, + factory, + router, + zrc20, + gasFee, + gasZRC20, + amount + ); + } + + uint256 outputAmount = SwapHelperLib._doSwap( + wzeta, + factory, + router, + zrc20, + isTargetZeta ? amount : amount - inputForGas, + targetTokenAddress, + 0 + ); + + if (!isTargetZeta) { + IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); + IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + } + } +} diff --git a/omnichain/swap/flat b/omnichain/swap/flat new file mode 100644 index 00000000..bb67950c --- /dev/null +++ b/omnichain/swap/flat @@ -0,0 +1,2453 @@ +// Sources flattened with hardhat v2.19.2 https://hardhat.org + +// SPDX-License-Identifier: MIT AND UNLICENSED + +// File @openzeppelin/contracts/token/ERC20/IERC20.sol@v4.9.6 + +// Original license: SPDX_License_Identifier: MIT +// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @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 @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol@v4.9.6 + +// Original license: SPDX_License_Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface for the optional metadata functions from the ERC20 standard. + * + * _Available since v4.1._ + */ +interface IERC20Metadata is IERC20 { + /** + * @dev Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the decimals places of the token. + */ + function decimals() external view returns (uint8); +} + + +// File @openzeppelin/contracts/utils/Context.sol@v4.9.6 + +// Original license: SPDX_License_Identifier: MIT +// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) + +pragma solidity ^0.8.0; + +/** + * @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; + } + + function _contextSuffixLength() internal view virtual returns (uint256) { + return 0; + } +} + + +// File @openzeppelin/contracts/token/ERC20/ERC20.sol@v4.9.6 + +// Original license: SPDX_License_Identifier: MIT +// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + + + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * The default value of {decimals} is 18. To change this, you should override + * this function so it returns a different value. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20 is Context, IERC20, IERC20Metadata { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the default value returned by this function, unless + * it's overridden. + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address to, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _transfer(owner, to, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + * - the caller must have allowance for ``from``'s tokens of at least + * `amount`. + */ + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, allowance(owner, spender) + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + address owner = _msgSender(); + uint256 currentAllowance = allowance(owner, spender); + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(owner, spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + */ + function _transfer(address from, address to, uint256 amount) internal virtual { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(from, to, amount); + + uint256 fromBalance = _balances[from]; + require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[from] = fromBalance - amount; + // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by + // decrementing then incrementing. + _balances[to] += amount; + } + + emit Transfer(from, to, amount); + + _afterTokenTransfer(from, to, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + unchecked { + // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. + _balances[account] += amount; + } + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + // Overflow not possible: amount <= accountBalance <= totalSupply. + _totalSupply -= amount; + } + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + 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); + } + + /** + * @dev Updates `owner` s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance amount in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Might emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require(currentAllowance >= amount, "ERC20: insufficient allowance"); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} +} + + +// File @uniswap/v2-core/contracts/interfaces/IUniswapV2ERC20.sol@v1.0.0 + +pragma solidity >=0.5.0; + +interface IUniswapV2ERC20 { + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + function name() external pure returns (string memory); + function symbol() external pure returns (string memory); + function decimals() external pure returns (uint8); + function totalSupply() external view returns (uint); + function balanceOf(address owner) external view returns (uint); + function allowance(address owner, address spender) external view returns (uint); + + function approve(address spender, uint value) external returns (bool); + function transfer(address to, uint value) external returns (bool); + function transferFrom(address from, address to, uint value) external returns (bool); + + function DOMAIN_SEPARATOR() external view returns (bytes32); + function PERMIT_TYPEHASH() external pure returns (bytes32); + function nonces(address owner) external view returns (uint); + + function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; +} + + +// File @uniswap/v2-core/contracts/libraries/SafeMath.sol@v1.0.0 + +pragma solidity =0.5.16; + +// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) + +library SafeMath { + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, 'ds-math-add-overflow'); + } + + function sub(uint x, uint y) internal pure returns (uint z) { + require((z = x - y) <= x, 'ds-math-sub-underflow'); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); + } +} + + +// File @uniswap/v2-core/contracts/UniswapV2ERC20.sol@v1.0.0 + +pragma solidity =0.5.16; + + +contract UniswapV2ERC20 is IUniswapV2ERC20 { + using SafeMath for uint; + + string public constant name = 'Uniswap V2'; + string public constant symbol = 'UNI-V2'; + uint8 public constant decimals = 18; + uint public totalSupply; + mapping(address => uint) public balanceOf; + mapping(address => mapping(address => uint)) public allowance; + + bytes32 public DOMAIN_SEPARATOR; + // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + mapping(address => uint) public nonces; + + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + constructor() public { + uint chainId; + assembly { + chainId := chainid + } + DOMAIN_SEPARATOR = keccak256( + abi.encode( + keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), + keccak256(bytes(name)), + keccak256(bytes('1')), + chainId, + address(this) + ) + ); + } + + function _mint(address to, uint value) internal { + totalSupply = totalSupply.add(value); + balanceOf[to] = balanceOf[to].add(value); + emit Transfer(address(0), to, value); + } + + function _burn(address from, uint value) internal { + balanceOf[from] = balanceOf[from].sub(value); + totalSupply = totalSupply.sub(value); + emit Transfer(from, address(0), value); + } + + function _approve(address owner, address spender, uint value) private { + allowance[owner][spender] = value; + emit Approval(owner, spender, value); + } + + function _transfer(address from, address to, uint value) private { + balanceOf[from] = balanceOf[from].sub(value); + balanceOf[to] = balanceOf[to].add(value); + emit Transfer(from, to, value); + } + + function approve(address spender, uint value) external returns (bool) { + _approve(msg.sender, spender, value); + return true; + } + + function transfer(address to, uint value) external returns (bool) { + _transfer(msg.sender, to, value); + return true; + } + + function transferFrom(address from, address to, uint value) external returns (bool) { + if (allowance[from][msg.sender] != uint(-1)) { + allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); + } + _transfer(from, to, value); + return true; + } + + function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { + require(deadline >= block.timestamp, 'UniswapV2: EXPIRED'); + bytes32 digest = keccak256( + abi.encodePacked( + '\x19\x01', + DOMAIN_SEPARATOR, + keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) + ) + ); + address recoveredAddress = ecrecover(digest, v, r, s); + require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE'); + _approve(owner, spender, value); + } +} + + +// File @uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol@v1.0.0 + +pragma solidity >=0.5.0; + +interface IUniswapV2Factory { + event PairCreated(address indexed token0, address indexed token1, address pair, uint); + + function feeTo() external view returns (address); + function feeToSetter() external view returns (address); + + function getPair(address tokenA, address tokenB) external view returns (address pair); + function allPairs(uint) external view returns (address pair); + function allPairsLength() external view returns (uint); + + function createPair(address tokenA, address tokenB) external returns (address pair); + + function setFeeTo(address) external; + function setFeeToSetter(address) external; +} + + +// File @uniswap/v2-core/contracts/interfaces/IERC20.sol@v1.0.0 + +pragma solidity >=0.5.0; + +interface IERC20 { + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + function name() external view returns (string memory); + function symbol() external view returns (string memory); + function decimals() external view returns (uint8); + function totalSupply() external view returns (uint); + function balanceOf(address owner) external view returns (uint); + function allowance(address owner, address spender) external view returns (uint); + + function approve(address spender, uint value) external returns (bool); + function transfer(address to, uint value) external returns (bool); + function transferFrom(address from, address to, uint value) external returns (bool); +} + + +// File @uniswap/v2-core/contracts/interfaces/IUniswapV2Callee.sol@v1.0.0 + +pragma solidity >=0.5.0; + +interface IUniswapV2Callee { + function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; +} + + +// File @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol@v1.0.0 + +pragma solidity >=0.5.0; + +interface IUniswapV2Pair { + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + function name() external pure returns (string memory); + function symbol() external pure returns (string memory); + function decimals() external pure returns (uint8); + function totalSupply() external view returns (uint); + function balanceOf(address owner) external view returns (uint); + function allowance(address owner, address spender) external view returns (uint); + + function approve(address spender, uint value) external returns (bool); + function transfer(address to, uint value) external returns (bool); + function transferFrom(address from, address to, uint value) external returns (bool); + + function DOMAIN_SEPARATOR() external view returns (bytes32); + function PERMIT_TYPEHASH() external pure returns (bytes32); + function nonces(address owner) external view returns (uint); + + function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; + + event Mint(address indexed sender, uint amount0, uint amount1); + event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); + event Swap( + address indexed sender, + uint amount0In, + uint amount1In, + uint amount0Out, + uint amount1Out, + address indexed to + ); + event Sync(uint112 reserve0, uint112 reserve1); + + function MINIMUM_LIQUIDITY() external pure returns (uint); + function factory() external view returns (address); + function token0() external view returns (address); + function token1() external view returns (address); + function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); + function price0CumulativeLast() external view returns (uint); + function price1CumulativeLast() external view returns (uint); + function kLast() external view returns (uint); + + function mint(address to) external returns (uint liquidity); + function burn(address to) external returns (uint amount0, uint amount1); + function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; + function skim(address to) external; + function sync() external; + + function initialize(address, address) external; +} + + +// File @uniswap/v2-core/contracts/libraries/Math.sol@v1.0.0 + +pragma solidity =0.5.16; + +// a library for performing various math operations + +library Math { + function min(uint x, uint y) internal pure returns (uint z) { + z = x < y ? x : y; + } + + // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) + function sqrt(uint y) internal pure returns (uint z) { + if (y > 3) { + z = y; + uint x = y / 2 + 1; + while (x < z) { + z = x; + x = (y / x + x) / 2; + } + } else if (y != 0) { + z = 1; + } + } +} + + +// File @uniswap/v2-core/contracts/libraries/UQ112x112.sol@v1.0.0 + +pragma solidity =0.5.16; + +// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) + +// range: [0, 2**112 - 1] +// resolution: 1 / 2**112 + +library UQ112x112 { + uint224 constant Q112 = 2**112; + + // encode a uint112 as a UQ112x112 + function encode(uint112 y) internal pure returns (uint224 z) { + z = uint224(y) * Q112; // never overflows + } + + // divide a UQ112x112 by a uint112, returning a UQ112x112 + function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { + z = x / uint224(y); + } +} + + +// File @uniswap/v2-core/contracts/UniswapV2Pair.sol@v1.0.0 + +pragma solidity =0.5.16; + + + + + + + +contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { + using SafeMath for uint; + using UQ112x112 for uint224; + + uint public constant MINIMUM_LIQUIDITY = 10**3; + bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); + + address public factory; + address public token0; + address public token1; + + uint112 private reserve0; // uses single storage slot, accessible via getReserves + uint112 private reserve1; // uses single storage slot, accessible via getReserves + uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves + + uint public price0CumulativeLast; + uint public price1CumulativeLast; + uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event + + uint private unlocked = 1; + modifier lock() { + require(unlocked == 1, 'UniswapV2: LOCKED'); + unlocked = 0; + _; + unlocked = 1; + } + + function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { + _reserve0 = reserve0; + _reserve1 = reserve1; + _blockTimestampLast = blockTimestampLast; + } + + function _safeTransfer(address token, address to, uint value) private { + (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED'); + } + + event Mint(address indexed sender, uint amount0, uint amount1); + event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); + event Swap( + address indexed sender, + uint amount0In, + uint amount1In, + uint amount0Out, + uint amount1Out, + address indexed to + ); + event Sync(uint112 reserve0, uint112 reserve1); + + constructor() public { + factory = msg.sender; + } + + // called once by the factory at time of deployment + function initialize(address _token0, address _token1) external { + require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check + token0 = _token0; + token1 = _token1; + } + + // update reserves and, on the first call per block, price accumulators + function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { + require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW'); + uint32 blockTimestamp = uint32(block.timestamp % 2**32); + uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired + if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { + // * never overflows, and + overflow is desired + price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; + price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; + } + reserve0 = uint112(balance0); + reserve1 = uint112(balance1); + blockTimestampLast = blockTimestamp; + emit Sync(reserve0, reserve1); + } + + // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) + function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { + address feeTo = IUniswapV2Factory(factory).feeTo(); + feeOn = feeTo != address(0); + uint _kLast = kLast; // gas savings + if (feeOn) { + if (_kLast != 0) { + uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); + uint rootKLast = Math.sqrt(_kLast); + if (rootK > rootKLast) { + uint numerator = totalSupply.mul(rootK.sub(rootKLast)); + uint denominator = rootK.mul(5).add(rootKLast); + uint liquidity = numerator / denominator; + if (liquidity > 0) _mint(feeTo, liquidity); + } + } + } else if (_kLast != 0) { + kLast = 0; + } + } + + // this low-level function should be called from a contract which performs important safety checks + function mint(address to) external lock returns (uint liquidity) { + (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings + uint balance0 = IERC20(token0).balanceOf(address(this)); + uint balance1 = IERC20(token1).balanceOf(address(this)); + uint amount0 = balance0.sub(_reserve0); + uint amount1 = balance1.sub(_reserve1); + + bool feeOn = _mintFee(_reserve0, _reserve1); + uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee + if (_totalSupply == 0) { + liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); + _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens + } else { + liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1); + } + require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED'); + _mint(to, liquidity); + + _update(balance0, balance1, _reserve0, _reserve1); + if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date + emit Mint(msg.sender, amount0, amount1); + } + + // this low-level function should be called from a contract which performs important safety checks + function burn(address to) external lock returns (uint amount0, uint amount1) { + (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings + address _token0 = token0; // gas savings + address _token1 = token1; // gas savings + uint balance0 = IERC20(_token0).balanceOf(address(this)); + uint balance1 = IERC20(_token1).balanceOf(address(this)); + uint liquidity = balanceOf[address(this)]; + + bool feeOn = _mintFee(_reserve0, _reserve1); + uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee + amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution + amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution + require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED'); + _burn(address(this), liquidity); + _safeTransfer(_token0, to, amount0); + _safeTransfer(_token1, to, amount1); + balance0 = IERC20(_token0).balanceOf(address(this)); + balance1 = IERC20(_token1).balanceOf(address(this)); + + _update(balance0, balance1, _reserve0, _reserve1); + if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date + emit Burn(msg.sender, amount0, amount1, to); + } + + // this low-level function should be called from a contract which performs important safety checks + function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { + require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT'); + (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings + require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY'); + + uint balance0; + uint balance1; + { // scope for _token{0,1}, avoids stack too deep errors + address _token0 = token0; + address _token1 = token1; + require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO'); + if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens + if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens + if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); + balance0 = IERC20(_token0).balanceOf(address(this)); + balance1 = IERC20(_token1).balanceOf(address(this)); + } + uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; + uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; + require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT'); + { // scope for reserve{0,1}Adjusted, avoids stack too deep errors + uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); + uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); + require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K'); + } + + _update(balance0, balance1, _reserve0, _reserve1); + emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); + } + + // force balances to match reserves + function skim(address to) external lock { + address _token0 = token0; // gas savings + address _token1 = token1; // gas savings + _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0)); + _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1)); + } + + // force reserves to match balances + function sync() external lock { + _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1); + } +} + + +// File @uniswap/v2-core/contracts/UniswapV2Factory.sol@v1.0.0 + +pragma solidity =0.5.16; + + +contract UniswapV2Factory is IUniswapV2Factory { + address public feeTo; + address public feeToSetter; + + mapping(address => mapping(address => address)) public getPair; + address[] public allPairs; + + event PairCreated(address indexed token0, address indexed token1, address pair, uint); + + constructor(address _feeToSetter) public { + feeToSetter = _feeToSetter; + } + + function allPairsLength() external view returns (uint) { + return allPairs.length; + } + + function createPair(address tokenA, address tokenB) external returns (address pair) { + require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES'); + (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); + require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS'); + require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient + bytes memory bytecode = type(UniswapV2Pair).creationCode; + bytes32 salt = keccak256(abi.encodePacked(token0, token1)); + assembly { + pair := create2(0, add(bytecode, 32), mload(bytecode), salt) + } + IUniswapV2Pair(pair).initialize(token0, token1); + getPair[token0][token1] = pair; + getPair[token1][token0] = pair; // populate mapping in the reverse direction + allPairs.push(pair); + emit PairCreated(token0, token1, pair, allPairs.length); + } + + function setFeeTo(address _feeTo) external { + require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); + feeTo = _feeTo; + } + + function setFeeToSetter(address _feeToSetter) external { + require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); + feeToSetter = _feeToSetter; + } +} + + +// File @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol@v1.1.0-beta.0 + +pragma solidity >=0.6.2; + +interface IUniswapV2Router01 { + function factory() external pure returns (address); + function WETH() external pure returns (address); + + function addLiquidity( + address tokenA, + address tokenB, + uint amountADesired, + uint amountBDesired, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB, uint liquidity); + function addLiquidityETH( + address token, + uint amountTokenDesired, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline + ) external payable returns (uint amountToken, uint amountETH, uint liquidity); + function removeLiquidity( + address tokenA, + address tokenB, + uint liquidity, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB); + function removeLiquidityETH( + address token, + uint liquidity, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline + ) external returns (uint amountToken, uint amountETH); + function removeLiquidityWithPermit( + address tokenA, + address tokenB, + uint liquidity, + uint amountAMin, + uint amountBMin, + address to, + uint deadline, + bool approveMax, uint8 v, bytes32 r, bytes32 s + ) external returns (uint amountA, uint amountB); + function removeLiquidityETHWithPermit( + address token, + uint liquidity, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline, + bool approveMax, uint8 v, bytes32 r, bytes32 s + ) external returns (uint amountToken, uint amountETH); + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + function swapTokensForExactTokens( + uint amountOut, + uint amountInMax, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) + external + payable + returns (uint[] memory amounts); + function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) + external + returns (uint[] memory amounts); + function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) + external + returns (uint[] memory amounts); + function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) + external + payable + returns (uint[] memory amounts); + + function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); + function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); + function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); + function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); + function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); +} + + +// File @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol@v1.1.0-beta.0 + +pragma solidity >=0.6.2; + +interface IUniswapV2Router02 is IUniswapV2Router01 { + function removeLiquidityETHSupportingFeeOnTransferTokens( + address token, + uint liquidity, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline + ) external returns (uint amountETH); + function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( + address token, + uint liquidity, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline, + bool approveMax, uint8 v, bytes32 r, bytes32 s + ) external returns (uint amountETH); + + function swapExactTokensForTokensSupportingFeeOnTransferTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external; + function swapExactETHForTokensSupportingFeeOnTransferTokens( + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external payable; + function swapExactTokensForETHSupportingFeeOnTransferTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external; +} + + +// File @zetachain/protocol-contracts/contracts/zevm/interfaces/IZRC20.sol@v7.0.0-rc1 + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.8.7; + +interface IZRC20 { + function totalSupply() external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); + + function transfer(address recipient, uint256 amount) external returns (bool); + + function allowance(address owner, address spender) external view returns (uint256); + + function approve(address spender, uint256 amount) external returns (bool); + + function decreaseAllowance(address spender, uint256 amount) external returns (bool); + + function increaseAllowance(address spender, uint256 amount) external returns (bool); + + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + function deposit(address to, uint256 amount) external returns (bool); + + function burn(address account, uint256 amount) external returns (bool); + + function withdraw(bytes memory to, uint256 amount) external returns (bool); + + function withdrawGasFee() external view returns (address, uint256); + + function PROTOCOL_FEE() external view returns (uint256); + + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + event Deposit(bytes from, address indexed to, uint256 value); + event Withdrawal(address indexed from, bytes to, uint256 value, uint256 gasFee, uint256 protocolFlatFee); + event UpdatedSystemContract(address systemContract); + event UpdatedGasLimit(uint256 gasLimit); + event UpdatedProtocolFlatFee(uint256 protocolFlatFee); +} + + +// File @zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol@v7.0.0-rc1 + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.8.7; + +struct zContext { + bytes origin; + address sender; + uint256 chainID; +} + +interface zContract { + function onCrossChainCall( + zContext calldata context, + address zrc20, + uint256 amount, + bytes calldata message + ) external; +} + + +// File @zetachain/protocol-contracts/contracts/zevm/SystemContract.sol@v7.0.0-rc1 + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.8.7; + + +/** + * @dev Custom errors for SystemContract + */ +interface SystemContractErrors { + error CallerIsNotFungibleModule(); + error InvalidTarget(); + error CantBeIdenticalAddresses(); + error CantBeZeroAddress(); + error ZeroAddress(); +} + +/** + * @dev The system contract it's called by the protocol to interact with the blockchain. + * Also includes a lot of tools to make easier to interact with ZetaChain. + */ +contract SystemContract is SystemContractErrors { + /// @notice Map to know the gas price of each chain given a chain id. + mapping(uint256 => uint256) public gasPriceByChainId; + /// @notice Map to know the ZRC20 address of a token given a chain id, ex zETH, zBNB etc. + mapping(uint256 => address) public gasCoinZRC20ByChainId; + // @dev: Map to know uniswap V2 pool of ZETA/ZRC20 given a chain id. This refer to the build in uniswap deployed at genesis. + mapping(uint256 => address) public gasZetaPoolByChainId; + + /// @notice Fungible address is always the same, it's on protocol level. + address public constant FUNGIBLE_MODULE_ADDRESS = 0x735b14BB79463307AAcBED86DAf3322B1e6226aB; + /// @notice Uniswap V2 addresses. + address public immutable uniswapv2FactoryAddress; + address public immutable uniswapv2Router02Address; + /// @notice Address of the wrapped ZETA to interact with Uniswap V2. + address public wZetaContractAddress; + /// @notice Address of ZEVM Zeta Connector. + address public zetaConnectorZEVMAddress; + + /// @notice Custom SystemContract errors. + event SystemContractDeployed(); + event SetGasPrice(uint256, uint256); + event SetGasCoin(uint256, address); + event SetGasZetaPool(uint256, address); + event SetWZeta(address); + event SetConnectorZEVM(address); + + /** + * @dev Only fungible module can deploy a system contract. + */ + constructor(address wzeta_, address uniswapv2Factory_, address uniswapv2Router02_) { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + wZetaContractAddress = wzeta_; + uniswapv2FactoryAddress = uniswapv2Factory_; + uniswapv2Router02Address = uniswapv2Router02_; + emit SystemContractDeployed(); + } + + /** + * @dev Deposit foreign coins into ZRC20 and call user specified contract on zEVM. + * @param context, context data for deposit. + * @param zrc20, zrc20 address for deposit. + * @param amount, amount to deposit. + * @param target, contract address to make a call after deposit. + * @param message, calldata for a call. + */ + function depositAndCall( + zContext calldata context, + address zrc20, + uint256 amount, + address target, + bytes calldata message + ) external { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + if (target == FUNGIBLE_MODULE_ADDRESS || target == address(this)) revert InvalidTarget(); + + IZRC20(zrc20).deposit(target, amount); + zContract(target).onCrossChainCall(context, zrc20, amount, message); + } + + /** + * @dev Sort token addresses lexicographically. Used to handle return values from pairs sorted in the order. + * @param tokenA, tokenA address. + * @param tokenB, tokenB address. + * @return token0 token1, returns sorted token addresses,. + */ + function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { + if (tokenA == tokenB) revert CantBeIdenticalAddresses(); + (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); + if (token0 == address(0)) revert CantBeZeroAddress(); + } + + /** + * @dev Calculates the CREATE2 address for a pair without making any external calls. + * @param factory, factory address. + * @param tokenA, tokenA address. + * @param tokenB, tokenB address. + * @return pair tokens pair address. + */ + function uniswapv2PairFor(address factory, address tokenA, address tokenB) public pure returns (address pair) { + (address token0, address token1) = sortTokens(tokenA, tokenB); + pair = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256(abi.encodePacked(token0, token1)), + hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash + ) + ) + ) + ) + ); + } + + /** + * @dev Fungible module updates the gas price oracle periodically. + * @param chainID, chain id. + * @param price, new gas price. + */ + function setGasPrice(uint256 chainID, uint256 price) external { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + gasPriceByChainId[chainID] = price; + emit SetGasPrice(chainID, price); + } + + /** + * @dev Setter for gasCoinZRC20ByChainId map. + * @param chainID, chain id. + * @param zrc20, ZRC20 address. + */ + function setGasCoinZRC20(uint256 chainID, address zrc20) external { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + gasCoinZRC20ByChainId[chainID] = zrc20; + emit SetGasCoin(chainID, zrc20); + } + + /** + * @dev Set the pool wzeta/erc20 address. + * @param chainID, chain id. + * @param erc20, pair for uniswap wzeta/erc20. + */ + function setGasZetaPool(uint256 chainID, address erc20) external { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + address pool = uniswapv2PairFor(uniswapv2FactoryAddress, wZetaContractAddress, erc20); + gasZetaPoolByChainId[chainID] = pool; + emit SetGasZetaPool(chainID, pool); + } + + /** + * @dev Setter for wrapped ZETA address. + * @param addr, wzeta new address. + */ + function setWZETAContractAddress(address addr) external { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + if (addr == address(0)) revert ZeroAddress(); + wZetaContractAddress = addr; + emit SetWZeta(wZetaContractAddress); + } + + /** + * @dev Setter for zetaConnector ZEVM Address + * @param addr, zeta connector new address. + */ + function setConnectorZEVMAddress(address addr) external { + if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); + if (addr == address(0)) revert ZeroAddress(); + zetaConnectorZEVMAddress = addr; + emit SetConnectorZEVM(zetaConnectorZEVMAddress); + } +} + + +// File @zetachain/toolkit/contracts/SwapHelperLib.sol@v7.0.0 + +// Original license: SPDX_License_Identifier: UNLICENSED +pragma solidity =0.8.7; + + + + +library SwapHelperLib { + uint16 internal constant MAX_DEADLINE = 200; + + error WrongGasContract(); + + error NotEnoughToPayGasFee(); + + error CantBeIdenticalAddresses(); + + error CantBeZeroAddress(); + + // returns sorted token addresses, used to handle return values from pairs sorted in this order + function sortTokens( + address tokenA, + address tokenB + ) internal pure returns (address token0, address token1) { + if (tokenA == tokenB) revert CantBeIdenticalAddresses(); + (token0, token1) = tokenA < tokenB + ? (tokenA, tokenB) + : (tokenB, tokenA); + if (token0 == address(0)) revert CantBeZeroAddress(); + } + + // calculates the CREATE2 address for a pair without making any external calls + function uniswapv2PairFor( + address factory, + address tokenA, + address tokenB + ) public pure returns (address pair) { + (address token0, address token1) = sortTokens(tokenA, tokenB); + pair = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256(abi.encodePacked(token0, token1)), + hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash + ) + ) + ) + ) + ); + } + + function _doWithdrawal( + address targetZRC20, + uint256 amount, + bytes32 receipient + ) internal { + (address gasZRC20, uint256 gasFee) = IZRC20(targetZRC20) + .withdrawGasFee(); + + if (gasZRC20 != targetZRC20) revert WrongGasContract(); + if (gasFee >= amount) revert NotEnoughToPayGasFee(); + + IZRC20(targetZRC20).approve(targetZRC20, gasFee); + IZRC20(targetZRC20).withdraw( + abi.encodePacked(receipient), + amount - gasFee + ); + } + + function _existsPairPool( + address uniswapV2Factory, + address zrc20A, + address zrc20B + ) internal view returns (bool) { + address uniswapPool = uniswapv2PairFor( + uniswapV2Factory, + zrc20A, + zrc20B + ); + return + IZRC20(zrc20A).balanceOf(uniswapPool) > 0 && + IZRC20(zrc20B).balanceOf(uniswapPool) > 0; + } + + function _doSwap( + address zetaToken, + address uniswapV2Factory, + address uniswapV2Router, + address zrc20, + uint256 amount, + address targetZRC20, + uint256 minAmountOut + ) internal returns (uint256) { + bool existsPairPool = _existsPairPool( + uniswapV2Factory, + zrc20, + targetZRC20 + ); + + address[] memory path; + if (existsPairPool) { + path = new address[](2); + path[0] = zrc20; + path[1] = targetZRC20; + } else { + path = new address[](3); + path[0] = zrc20; + path[1] = zetaToken; + path[2] = targetZRC20; + } + + IZRC20(zrc20).approve(address(uniswapV2Router), amount); + uint256[] memory amounts = IUniswapV2Router01(uniswapV2Router) + .swapExactTokensForTokens( + amount, + minAmountOut, + path, + address(this), + block.timestamp + MAX_DEADLINE + ); + return amounts[path.length - 1]; + } + + function swapTokensForExactTokens( + address zetaToken, + address uniswapV2Factory, + address uniswapV2Router, + address zrc20, + uint256 amount, + address targetZRC20, + uint256 amountInMax + ) internal returns (uint256) { + bool existsPairPool = _existsPairPool( + uniswapV2Factory, + zrc20, + targetZRC20 + ); + + address[] memory path; + if (existsPairPool) { + path = new address[](2); + path[0] = zrc20; + path[1] = targetZRC20; + } else { + path = new address[](3); + path[0] = zrc20; + path[1] = zetaToken; + path[2] = targetZRC20; + } + + IZRC20(zrc20).approve(address(uniswapV2Router), amountInMax); + uint256[] memory amounts = IUniswapV2Router01(uniswapV2Router) + .swapTokensForExactTokens( + amount, + amountInMax, + path, + address(this), + block.timestamp + MAX_DEADLINE + ); + return amounts[0]; + } +} + + +// File contracts/shared/libraries/SafeMath.sol + +pragma solidity =0.6.6; + +// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) + +library SafeMath { + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, 'ds-math-add-overflow'); + } + + function sub(uint x, uint y) internal pure returns (uint z) { + require((z = x - y) <= x, 'ds-math-sub-underflow'); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); + } +} + + +// File contracts/shared/libraries/UniswapV2Library.sol + +pragma solidity >=0.5.0; + + +library UniswapV2Library { + using SafeMath for uint; + + // returns sorted token addresses, used to handle return values from pairs sorted in this order + function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { + require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES'); + (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); + require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS'); + } + + // calculates the CREATE2 address for a pair without making any external calls + function pairFor(address factory, address tokenA, address tokenB) internal view returns (address pair) { + // Not working + // (address token0, address token1) = sortTokens(tokenA, tokenB); + // pair = address(uint(keccak256(abi.encodePacked( + // hex'ff', + // factory, + // keccak256(abi.encodePacked(token0, token1)), + // hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash + // )))); + pair = IUniswapV2Factory(factory).getPair(tokenA, tokenB); + } + + // fetches and sorts the reserves for a pair + function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) { + (address token0,) = sortTokens(tokenA, tokenB); + (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves(); + (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); + } + + // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset + function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { + require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT'); + require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); + amountB = amountA.mul(reserveB) / reserveA; + } + + // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset + function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { + require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT'); + require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); + uint amountInWithFee = amountIn.mul(997); + uint numerator = amountInWithFee.mul(reserveOut); + uint denominator = reserveIn.mul(1000).add(amountInWithFee); + amountOut = numerator / denominator; + } + + // given an output amount of an asset and pair reserves, returns a required input amount of the other asset + function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { + require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT'); + require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); + uint numerator = reserveIn.mul(amountOut).mul(1000); + uint denominator = reserveOut.sub(amountOut).mul(997); + amountIn = (numerator / denominator).add(1); + } + + // performs chained getAmountOut calculations on any number of pairs + function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) { + require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); + amounts = new uint[](path.length); + amounts[0] = amountIn; + for (uint i; i < path.length - 1; i++) { + (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]); + amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); + } + } + + // performs chained getAmountIn calculations on any number of pairs + function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) { + require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); + amounts = new uint[](path.length); + amounts[amounts.length - 1] = amountOut; + for (uint i = path.length - 1; i > 0; i--) { + (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]); + amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); + } + } +} + + +// File contracts/shared/MockSystemContract.sol + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.8.7; + + +interface SystemContractErrors { + error CallerIsNotFungibleModule(); + + error InvalidTarget(); + + error CantBeIdenticalAddresses(); + + error CantBeZeroAddress(); +} + +contract MockSystemContract is SystemContractErrors { + error TransferFailed(); + + mapping(uint256 => uint256) public gasPriceByChainId; + mapping(uint256 => address) public gasCoinZRC20ByChainId; + mapping(uint256 => address) public gasZetaPoolByChainId; + + address public wZetaContractAddress; + address public immutable uniswapv2FactoryAddress; + address public immutable uniswapv2Router02Address; + + event SystemContractDeployed(); + event SetGasPrice(uint256, uint256); + event SetGasCoin(uint256, address); + event SetGasZetaPool(uint256, address); + event SetWZeta(address); + + constructor(address wzeta_, address uniswapv2Factory_, address uniswapv2Router02_) { + wZetaContractAddress = wzeta_; + uniswapv2FactoryAddress = uniswapv2Factory_; + uniswapv2Router02Address = uniswapv2Router02_; + emit SystemContractDeployed(); + } + + // fungible module updates the gas price oracle periodically + function setGasPrice(uint256 chainID, uint256 price) external { + gasPriceByChainId[chainID] = price; + emit SetGasPrice(chainID, price); + } + + function setGasCoinZRC20(uint256 chainID, address zrc20) external { + gasCoinZRC20ByChainId[chainID] = zrc20; + emit SetGasCoin(chainID, zrc20); + } + + function setWZETAContractAddress(address addr) external { + wZetaContractAddress = addr; + emit SetWZeta(wZetaContractAddress); + } + + // returns sorted token addresses, used to handle return values from pairs sorted in this order + function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { + if (tokenA == tokenB) revert CantBeIdenticalAddresses(); + (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); + if (token0 == address(0)) revert CantBeZeroAddress(); + } + + function uniswapv2PairFor(address factory, address tokenA, address tokenB) public pure returns (address pair) { + (address token0, address token1) = sortTokens(tokenA, tokenB); + pair = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256(abi.encodePacked(token0, token1)), + hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash + ) + ) + ) + ) + ); + } + + function onCrossChainCall(uint256 chainID, address target, address zrc20, uint256 amount, bytes calldata message) external { + zContext memory context = zContext({sender: msg.sender, origin: "", chainID: chainID}); + bool transfer = IZRC20(zrc20).transfer(target, amount); + if (!transfer) revert TransferFailed(); + zContract(target).onCrossChainCall(context, zrc20, amount, message); + } +} + + +// File @zetachain/toolkit/contracts/BytesHelperLib.sol@v7.0.0 + +// Original license: SPDX_License_Identifier: UNLICENSED +pragma solidity =0.8.7; + +library BytesHelperLib { + function bytesToAddress( + bytes calldata data, + uint256 offset + ) internal pure returns (address output) { + bytes memory b = data[offset:offset + 20]; + assembly { + output := mload(add(b, 20)) + } + } + + function bytesMemoryToAddress( + bytes memory data, + uint256 offset + ) internal pure returns (address output) { + assembly { + output := mload(add(add(data, offset), 32)) + } + } + + function bytesToUint32( + bytes calldata data, + uint256 offset + ) internal pure returns (uint32 output) { + bytes memory b = data[offset:offset + 4]; + assembly { + output := mload(add(b, 4)) + } + } + + function addressToBytes( + address someAddress + ) internal pure returns (bytes32) { + return bytes32(uint256(uint160(someAddress))); + } + + function bytesToBech32Bytes( + bytes calldata data, + uint256 offset + ) internal pure returns (bytes memory) { + bytes memory bech32Bytes = new bytes(42); + for (uint i = 0; i < 42; i++) { + bech32Bytes[i] = data[i + offset]; + } + + return bech32Bytes; + } +} + + +// File contracts/shared/MockZRC20.sol + +// Original license: SPDX_License_Identifier: MIT +pragma solidity =0.8.7; + + + +contract MockZRC20 is ERC20 { + address public gasFeeAddress; + uint256 public gasFee; + + event Withdrawal(address indexed from, bytes to, uint256 value, uint256 gasfee, uint256 protocolFlatFee); + + constructor(uint256 initialSupply, string memory name, string memory symbol) ERC20(name, symbol) { + _mint(msg.sender, initialSupply * (10 ** uint256(decimals()))); + gasFeeAddress = address(this); + } + + function setGasFeeAddress(address gasFeeAddress_) external { + gasFeeAddress = gasFeeAddress_; + } + + function setGasFee(uint256 gasFee_) external { + gasFee = gasFee_; + } + + function deposit(address to, uint256 amount) external returns (bool) { + return true; + } + + function bytesToAddress(bytes calldata data, uint256 offset, uint256 size) public pure returns (address output) { + bytes memory b = data[offset:offset + size]; + assembly { + output := mload(add(b, size)) + } + } + + function withdraw(bytes calldata to, uint256 amount) external returns (bool) { + address toAddress; + if (to.length < 32) { + toAddress = BytesHelperLib.bytesToAddress(to, 0); + } else { + toAddress = BytesHelperLib.bytesToAddress(to, 12); + } + + emit Withdrawal(msg.sender, to, amount, gasFee, 0); + return transfer(toAddress, amount); + } + + function withdrawGasFee() external view returns (address, uint256) { + return (gasFeeAddress, gasFee); + } +} + + +// File contracts/shared/TestUniswapCore.sol + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.5.16; + +/** + * @dev Contracts that need to be compiled for testing purposes + */ + + +// File @uniswap/lib/contracts/libraries/TransferHelper.sol@v1.1.1 + +pragma solidity >=0.6.0; + +// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false +library TransferHelper { + function safeApprove(address token, address to, uint value) internal { + // bytes4(keccak256(bytes('approve(address,uint256)'))); + (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); + } + + function safeTransfer(address token, address to, uint value) internal { + // bytes4(keccak256(bytes('transfer(address,uint256)'))); + (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); + } + + function safeTransferFrom(address token, address from, address to, uint value) internal { + // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); + (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); + } + + function safeTransferETH(address to, uint value) internal { + (bool success,) = to.call{value:value}(new bytes(0)); + require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); + } +} + + +// File contracts/shared/interfaces/IERC20.sol + +pragma solidity >=0.5.0; + +interface IERC20 { + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + function name() external view returns (string memory); + function symbol() external view returns (string memory); + function decimals() external view returns (uint8); + function totalSupply() external view returns (uint); + function balanceOf(address owner) external view returns (uint); + function allowance(address owner, address spender) external view returns (uint); + + function approve(address spender, uint value) external returns (bool); + function transfer(address to, uint value) external returns (bool); + function transferFrom(address from, address to, uint value) external returns (bool); +} + + +// File contracts/shared/interfaces/IWETH.sol + +pragma solidity >=0.5.0; + +interface IWETH { + function deposit() external payable; + function transfer(address to, uint value) external returns (bool); + function withdraw(uint) external; +} + + +// File contracts/shared/TestUniswapRouter.sol + +pragma solidity =0.6.6; + + + + + +contract TestUniswapRouter { + using SafeMath for uint; + + address public immutable factory; + address public immutable WETH; + + modifier ensure(uint deadline) { + require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED'); + _; + } + + constructor(address _factory, address _WETH) public { + factory = _factory; + WETH = _WETH; + } + + receive() external payable { + assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract + } + + // **** ADD LIQUIDITY **** + function _addLiquidity( + address tokenA, + address tokenB, + uint amountADesired, + uint amountBDesired, + uint amountAMin, + uint amountBMin + ) internal returns (uint amountA, uint amountB) { + // create the pair if it doesn't exist yet + if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) { + address pair = IUniswapV2Factory(factory).createPair(tokenA, tokenB); + } + + (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB); + if (reserveA == 0 && reserveB == 0) { + (amountA, amountB) = (amountADesired, amountBDesired); + } else { + uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB); + if (amountBOptimal <= amountBDesired) { + require(amountBOptimal >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); + (amountA, amountB) = (amountADesired, amountBOptimal); + } else { + uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA); + assert(amountAOptimal <= amountADesired); + require(amountAOptimal >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); + (amountA, amountB) = (amountAOptimal, amountBDesired); + } + } + } + function addLiquidity( + address tokenA, + address tokenB, + uint amountADesired, + uint amountBDesired, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) { + (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin); + address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); + TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA); + TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); + liquidity = IUniswapV2Pair(pair).mint(to); + } + function addLiquidityETH( + address token, + uint amountTokenDesired, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline + ) external payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) { + (amountToken, amountETH) = _addLiquidity( + token, + WETH, + amountTokenDesired, + msg.value, + amountTokenMin, + amountETHMin + ); + address pair = UniswapV2Library.pairFor(factory, token, WETH); + TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); + IWETH(WETH).deposit{value: amountETH}(); + assert(IWETH(WETH).transfer(pair, amountETH)); + liquidity = IUniswapV2Pair(pair).mint(to); + // refund dust eth, if any + if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); + + } + + // **** REMOVE LIQUIDITY **** + function removeLiquidity( + address tokenA, + address tokenB, + uint liquidity, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) public ensure(deadline) returns (uint amountA, uint amountB) { + address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); + IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair + (uint amount0, uint amount1) = IUniswapV2Pair(pair).burn(to); + (address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB); + (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); + require(amountA >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); + require(amountB >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); + } + function removeLiquidityETH( + address token, + uint liquidity, + uint amountTokenMin, + uint amountETHMin, + address to, + uint deadline + ) public ensure(deadline) returns (uint amountToken, uint amountETH) { + (amountToken, amountETH) = removeLiquidity( + token, + WETH, + liquidity, + amountTokenMin, + amountETHMin, + address(this), + deadline + ); + TransferHelper.safeTransfer(token, to, amountToken); + IWETH(WETH).withdraw(amountETH); + TransferHelper.safeTransferETH(to, amountETH); + } + + // **** SWAP **** + // requires the initial amount to have already been sent to the first pair + function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual { + for (uint i; i < path.length - 1; i++) { + (address input, address output) = (path[i], path[i + 1]); + (address token0,) = UniswapV2Library.sortTokens(input, output); + uint amountOut = amounts[i + 1]; + (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0)); + address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to; + IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)).swap( + amount0Out, amount1Out, to, new bytes(0) + ); + } + } + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external ensure(deadline) returns (uint[] memory amounts) { + amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); + require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); + TransferHelper.safeTransferFrom( + path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] + ); + _swap(amounts, path, to); + } + function swapTokensForExactTokens( + uint amountOut, + uint amountInMax, + address[] calldata path, + address to, + uint deadline + ) external ensure(deadline) returns (uint[] memory amounts) { + amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); + require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT'); + TransferHelper.safeTransferFrom( + path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] + ); + _swap(amounts, path, to); + } + + // **** LIBRARY FUNCTIONS **** + function quote(uint amountA, uint reserveA, uint reserveB) public pure returns (uint amountB) { + return UniswapV2Library.quote(amountA, reserveA, reserveB); + } + + function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) + public + pure + returns (uint amountOut) + { + return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); + } + + function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) + public + pure + returns (uint amountIn) + { + return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); + } + + function getAmountsOut(uint amountIn, address[] memory path) + public + view + returns (uint[] memory amounts) + { + return UniswapV2Library.getAmountsOut(factory, amountIn, path); + } + + function getAmountsIn(uint amountOut, address[] memory path) + public + view + returns (uint[] memory amounts) + { + return UniswapV2Library.getAmountsIn(factory, amountOut, path); + } +} + + +// File contracts/Swap.sol + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.8.7; + + + + +contract Swap is zContract { + SystemContract public immutable systemContract; + uint256 constant BITCOIN = 18332; + + constructor(address systemContractAddress) { + systemContract = SystemContract(systemContractAddress); + } + + modifier onlySystem() { + require( + msg.sender == address(systemContract), + "Only system contract can call this function" + ); + _; + } + + function onCrossChainCall( + zContext calldata context, + address zrc20, + uint256 amount, + bytes calldata message + ) external virtual override onlySystem { + address targetTokenAddress; + bytes memory recipientAddress; + + if (context.chainID == BITCOIN) { + targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); + recipientAddress = abi.encodePacked( + BytesHelperLib.bytesToAddress(message, 20) + ); + } else { + (address targetToken, bytes memory recipient) = abi.decode( + message, + (address, bytes) + ); + targetTokenAddress = targetToken; + recipientAddress = recipient; + } + + (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) + .withdrawGasFee(); + + uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( + systemContract.wZetaContractAddress(), + systemContract.uniswapv2FactoryAddress(), + systemContract.uniswapv2Router02Address(), + zrc20, + gasFee, + gasZRC20, + amount + ); + + uint256 outputAmount = SwapHelperLib._doSwap( + systemContract.wZetaContractAddress(), + systemContract.uniswapv2FactoryAddress(), + systemContract.uniswapv2Router02Address(), + zrc20, + amount - inputForGas, + targetTokenAddress, + 0 + ); + + IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); + IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + } +} + + +// File contracts/SwapExtended.sol + +// Original license: SPDX_License_Identifier: MIT +pragma solidity 0.8.7; + + + + + +contract SwapExtended is zContract { + SystemContract public systemContract; + address public wzeta; + address public factory; + address public router; + + uint256 constant BITCOIN = 18332; + + constructor(address systemContractAddress) { + systemContract = SystemContract(systemContractAddress); + wzeta = systemContract.wZetaContractAddress(); + factory = systemContract.uniswapv2FactoryAddress(); + router = systemContract.uniswapv2Router02Address(); + } + + modifier onlySystem() { + require( + msg.sender == address(systemContract), + "Only system contract can call this function" + ); + _; + } + + function onCrossChainCall( + zContext calldata context, + address zrc20, + uint256 amount, + bytes calldata message + ) external virtual override onlySystem { + address targetTokenAddress; + bytes memory recipientAddress; + + if (context.chainID == BITCOIN) { + targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); + recipientAddress = abi.encodePacked( + BytesHelperLib.bytesToAddress(message, 20) + ); + } else { + (address targetToken, bytes memory recipient) = abi.decode( + message, + (address, bytes) + ); + targetTokenAddress = targetToken; + recipientAddress = recipient; + } + + bool isTargetZeta = targetTokenAddress == wzeta; + uint256 inputForGas; + address gasZRC20; + uint256 gasFee; + + if (!isTargetZeta) { + (gasZRC20, gasFee) = IZRC20(targetTokenAddress).withdrawGasFee(); + + inputForGas = SwapHelperLib.swapTokensForExactTokens( + wzeta, + factory, + router, + zrc20, + gasFee, + gasZRC20, + amount + ); + } + + uint256 outputAmount = SwapHelperLib._doSwap( + wzeta, + factory, + router, + zrc20, + isTargetZeta ? amount : amount - inputForGas, + targetTokenAddress, + 0 + ); + + if (!isTargetZeta) { + IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); + IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + } + } +} + + +// File contracts/shared/WZETA.sol + +pragma solidity ^0.4.18; + +contract WZETA { + string public name = "Wrapped Zeta"; + string public symbol = "WZETA"; + uint8 public decimals = 18; + + 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; + + function() public payable { + deposit(); + } + + function deposit() public payable { + balanceOf[msg.sender] += msg.value; + Deposit(msg.sender, msg.value); + } + + function withdraw(uint wad) public { + require(balanceOf[msg.sender] >= wad); + balanceOf[msg.sender] -= wad; + msg.sender.transfer(wad); + Withdrawal(msg.sender, wad); + } + + function totalSupply() public view returns (uint) { + return this.balance; + } + + function approve(address guy, uint wad) public returns (bool) { + allowance[msg.sender][guy] = wad; + 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] != uint(-1)) { + require(allowance[src][msg.sender] >= wad); + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + Transfer(src, dst, wad); + + return true; + } +} diff --git a/omnichain/swap/tasks/deploy.ts b/omnichain/swap/tasks/deploy.ts index bdb943b4..d10bbecb 100644 --- a/omnichain/swap/tasks/deploy.ts +++ b/omnichain/swap/tasks/deploy.ts @@ -18,7 +18,7 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { const systemContract = getAddress("systemContract", "zeta_testnet"); - const factory = await hre.ethers.getContractFactory("Swap"); + const factory = await hre.ethers.getContractFactory(args.name); const contract = await factory.deploy(systemContract); await contract.deployed(); @@ -34,7 +34,6 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { } }; -task("deploy", "Deploy the contract", main).addFlag( - "json", - "Output in JSON" -); \ No newline at end of file +task("deploy", "Deploy the contract", main) + .addFlag("json", "Output in JSON") + .addOptionalParam("name", "Contract to deploy", "Swap"); From ca0b53f52359277e4843a1dc7f6d941a43b656df Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 9 May 2024 11:50:16 +0300 Subject: [PATCH 04/13] update to toolkit v8-rc1 --- omnichain/swap/contracts/Swap.sol | 12 +++---- omnichain/swap/contracts/SwapExtended.sol | 42 ++++++++--------------- omnichain/swap/package.json | 2 +- omnichain/swap/tasks/deploy.ts | 19 ++++++---- omnichain/swap/yarn.lock | 8 ++--- 5 files changed, 37 insertions(+), 46 deletions(-) diff --git a/omnichain/swap/contracts/Swap.sol b/omnichain/swap/contracts/Swap.sol index 4e2152c8..f5f33e0c 100644 --- a/omnichain/swap/contracts/Swap.sol +++ b/omnichain/swap/contracts/Swap.sol @@ -7,7 +7,7 @@ import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; contract Swap is zContract { - SystemContract public immutable systemContract; + SystemContract public systemContract; uint256 constant BITCOIN = 18332; constructor(address systemContractAddress) { @@ -49,19 +49,15 @@ contract Swap is zContract { .withdrawGasFee(); uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), + systemContract, zrc20, gasFee, gasZRC20, amount ); - uint256 outputAmount = SwapHelperLib._doSwap( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), + uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens( + systemContract, zrc20, amount - inputForGas, targetTokenAddress, diff --git a/omnichain/swap/contracts/SwapExtended.sol b/omnichain/swap/contracts/SwapExtended.sol index f919e774..d97a5458 100644 --- a/omnichain/swap/contracts/SwapExtended.sol +++ b/omnichain/swap/contracts/SwapExtended.sol @@ -7,19 +7,13 @@ import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -contract SwapExtended is zContract { +contract SwapZeta is zContract { SystemContract public systemContract; - address public wzeta; - address public factory; - address public router; uint256 constant BITCOIN = 18332; constructor(address systemContractAddress) { systemContract = SystemContract(systemContractAddress); - wzeta = systemContract.wZetaContractAddress(); - factory = systemContract.uniswapv2FactoryAddress(); - router = systemContract.uniswapv2Router02Address(); } modifier onlySystem() { @@ -36,35 +30,31 @@ contract SwapExtended is zContract { uint256 amount, bytes calldata message ) external virtual override onlySystem { - address targetTokenAddress; - bytes memory recipientAddress; + address target; + bytes memory to; if (context.chainID == BITCOIN) { - targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); - recipientAddress = abi.encodePacked( - BytesHelperLib.bytesToAddress(message, 20) - ); + target = BytesHelperLib.bytesToAddress(message, 0); + to = abi.encodePacked(BytesHelperLib.bytesToAddress(message, 20)); } else { (address targetToken, bytes memory recipient) = abi.decode( message, (address, bytes) ); - targetTokenAddress = targetToken; - recipientAddress = recipient; + target = targetToken; + to = recipient; } - bool isTargetZeta = targetTokenAddress == wzeta; + bool isTargetZeta = target == systemContract.wZetaContractAddress(); uint256 inputForGas; address gasZRC20; uint256 gasFee; if (!isTargetZeta) { - (gasZRC20, gasFee) = IZRC20(targetTokenAddress).withdrawGasFee(); + (gasZRC20, gasFee) = IZRC20(target).withdrawGasFee(); inputForGas = SwapHelperLib.swapTokensForExactTokens( - wzeta, - factory, - router, + systemContract, zrc20, gasFee, gasZRC20, @@ -72,19 +62,17 @@ contract SwapExtended is zContract { ); } - uint256 outputAmount = SwapHelperLib._doSwap( - wzeta, - factory, - router, + uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens( + systemContract, zrc20, isTargetZeta ? amount : amount - inputForGas, - targetTokenAddress, + target, 0 ); if (!isTargetZeta) { - IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); - IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + IZRC20(gasZRC20).approve(target, gasFee); + IZRC20(target).withdraw(to, outputAmount); } } } diff --git a/omnichain/swap/package.json b/omnichain/swap/package.json index 01eff927..031fd967 100644 --- a/omnichain/swap/package.json +++ b/omnichain/swap/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0-rc1", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/swap/tasks/deploy.ts b/omnichain/swap/tasks/deploy.ts index d10bbecb..91901182 100644 --- a/omnichain/swap/tasks/deploy.ts +++ b/omnichain/swap/tasks/deploy.ts @@ -1,11 +1,13 @@ -import { getAddress } from "@zetachain/protocol-contracts"; +import { getAddress, ParamChainName } from "@zetachain/protocol-contracts"; import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - if (hre.network.name !== "zeta_testnet") { + const network = hre.network.name as ParamChainName; + + if (!/zeta_(testnet|mainnet)/.test(network)) { throw new Error( - '🚨 Please use the "zeta_testnet" network to deploy to ZetaChain.' + '🚨 Please use either "zeta_testnet" or "zeta_mainnet" network to deploy to ZetaChain.' ); } @@ -16,20 +18,25 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { ); } - const systemContract = getAddress("systemContract", "zeta_testnet"); + const systemContract = getAddress("systemContract", network); const factory = await hre.ethers.getContractFactory(args.name); const contract = await factory.deploy(systemContract); await contract.deployed(); + const isTestnet = network === "zeta_testnet"; + const zetascan = isTestnet ? "athens.explorer" : "explorer"; + const blockscout = isTestnet ? "zetachain-athens-3" : "zetachain"; + if (args.json) { console.log(JSON.stringify(contract)); } else { console.log(`🔑 Using account: ${signer.address} -🚀 Successfully deployed contract on ZetaChain. +🚀 Successfully deployed contract on ${network}. 📜 Contract address: ${contract.address} -🌍 Explorer: https://athens3.explorer.zetachain.com/address/${contract.address} +🌍 ZetaScan: https://${zetascan}.zetachain.com/address/${contract.address} +🌍 Blockcsout: https://${blockscout}.blockscout.com/address/${contract.address} `); } }; diff --git a/omnichain/swap/yarn.lock b/omnichain/swap/yarn.lock index 474b5ff3..ad316b1b 100644 --- a/omnichain/swap/yarn.lock +++ b/omnichain/swap/yarn.lock @@ -1736,10 +1736,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0-rc1": + version "8.0.0-rc1" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc1.tgz#f7ef34393e63a7e33c2e7b27c307b9423972151f" + integrity sha512-V0uqIQgfYDCg2Ni4ccy6Il3IdOjgOZ5nISTURidq4wocLDAPQHl0yoos9GoVqL5QYa49WLFFEL8lRXouU0qz3g== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" From a2201265941aa65bf023bb95fe00f150bf9b011b Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 9 May 2024 12:27:32 +0300 Subject: [PATCH 05/13] shorter var names --- omnichain/swap/contracts/Swap.sol | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/omnichain/swap/contracts/Swap.sol b/omnichain/swap/contracts/Swap.sol index f5f33e0c..f74ff840 100644 --- a/omnichain/swap/contracts/Swap.sol +++ b/omnichain/swap/contracts/Swap.sol @@ -28,25 +28,22 @@ contract Swap is zContract { uint256 amount, bytes calldata message ) external virtual override onlySystem { - address targetTokenAddress; - bytes memory recipientAddress; + address target; + bytes memory to; if (context.chainID == BITCOIN) { - targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); - recipientAddress = abi.encodePacked( - BytesHelperLib.bytesToAddress(message, 20) - ); + target = BytesHelperLib.bytesToAddress(message, 0); + to = abi.encodePacked(BytesHelperLib.bytesToAddress(message, 20)); } else { (address targetToken, bytes memory recipient) = abi.decode( message, (address, bytes) ); - targetTokenAddress = targetToken; - recipientAddress = recipient; + target = targetToken; + to = recipient; } - (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) - .withdrawGasFee(); + (address gasZRC20, uint256 gasFee) = IZRC20(target).withdrawGasFee(); uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( systemContract, @@ -60,11 +57,11 @@ contract Swap is zContract { systemContract, zrc20, amount - inputForGas, - targetTokenAddress, + target, 0 ); - IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); - IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); + IZRC20(gasZRC20).approve(target, gasFee); + IZRC20(target).withdraw(to, outputAmount); } } From d0a4fc6329e135c006931d5835e854f9211e4960 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 9 May 2024 12:30:24 +0300 Subject: [PATCH 06/13] rename to SwapToZeta --- omnichain/swap/contracts/{SwapExtended.sol => SwapToZeta.sol} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename omnichain/swap/contracts/{SwapExtended.sol => SwapToZeta.sol} (98%) diff --git a/omnichain/swap/contracts/SwapExtended.sol b/omnichain/swap/contracts/SwapToZeta.sol similarity index 98% rename from omnichain/swap/contracts/SwapExtended.sol rename to omnichain/swap/contracts/SwapToZeta.sol index d97a5458..efd03025 100644 --- a/omnichain/swap/contracts/SwapExtended.sol +++ b/omnichain/swap/contracts/SwapToZeta.sol @@ -7,7 +7,7 @@ import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -contract SwapZeta is zContract { +contract SwapToZeta is zContract { SystemContract public systemContract; uint256 constant BITCOIN = 18332; From 740718ce2ff206cda79b0237251c8c03fd447fea Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 9 May 2024 12:55:11 +0300 Subject: [PATCH 07/13] transfer ZETA to recipient --- omnichain/swap/contracts/SwapToZeta.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/omnichain/swap/contracts/SwapToZeta.sol b/omnichain/swap/contracts/SwapToZeta.sol index efd03025..c7ce4418 100644 --- a/omnichain/swap/contracts/SwapToZeta.sol +++ b/omnichain/swap/contracts/SwapToZeta.sol @@ -45,7 +45,8 @@ contract SwapToZeta is zContract { to = recipient; } - bool isTargetZeta = target == systemContract.wZetaContractAddress(); + address wzeta = systemContract.wZetaContractAddress(); + bool isTargetZeta = target == wzeta; uint256 inputForGas; address gasZRC20; uint256 gasFee; @@ -70,7 +71,9 @@ contract SwapToZeta is zContract { 0 ); - if (!isTargetZeta) { + if (isTargetZeta) { + IERC20(wzeta).transfer(address(uint160(bytes20(to))), outputAmount); + } else { IZRC20(gasZRC20).approve(target, gasFee); IZRC20(target).withdraw(to, outputAmount); } From 615a134401280c7810478725a0d24b21280a9baf Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 9 May 2024 15:09:09 +0300 Subject: [PATCH 08/13] weth --- omnichain/swap/contracts/SwapToZeta.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omnichain/swap/contracts/SwapToZeta.sol b/omnichain/swap/contracts/SwapToZeta.sol index c7ce4418..570b155f 100644 --- a/omnichain/swap/contracts/SwapToZeta.sol +++ b/omnichain/swap/contracts/SwapToZeta.sol @@ -5,7 +5,7 @@ import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@zetachain/protocol-contracts/contracts/zevm/interfaces/IWZETA.sol"; contract SwapToZeta is zContract { SystemContract public systemContract; @@ -72,7 +72,7 @@ contract SwapToZeta is zContract { ); if (isTargetZeta) { - IERC20(wzeta).transfer(address(uint160(bytes20(to))), outputAmount); + IWETH9(wzeta).transfer(address(uint160(bytes20(to))), outputAmount); } else { IZRC20(gasZRC20).approve(target, gasFee); IZRC20(target).withdraw(to, outputAmount); From 29da289aa93b955a0982611dd6dc47429b50109b Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Mon, 13 May 2024 18:15:02 +0400 Subject: [PATCH 09/13] toolkit v8-rc3 --- .../multioutput/contracts/Multioutput.sol | 31 +--- omnichain/multioutput/package.json | 6 +- omnichain/multioutput/yarn.lock | 174 +++++++++++++++++- omnichain/nft/contracts/NFT.sol | 23 +-- omnichain/nft/package.json | 2 +- omnichain/nft/yarn.lock | 8 +- omnichain/staking/contracts/Staking.sol | 15 +- omnichain/staking/package.json | 2 +- omnichain/staking/yarn.lock | 8 +- omnichain/swap/contracts/Swap.sol | 36 ++-- omnichain/swap/contracts/SwapToZeta.sol | 13 +- omnichain/swap/package.json | 2 +- omnichain/swap/yarn.lock | 8 +- package.json | 5 +- 14 files changed, 229 insertions(+), 104 deletions(-) diff --git a/omnichain/multioutput/contracts/Multioutput.sol b/omnichain/multioutput/contracts/Multioutput.sol index eb9ccdec..6ff9b145 100644 --- a/omnichain/multioutput/contracts/Multioutput.sol +++ b/omnichain/multioutput/contracts/Multioutput.sol @@ -6,15 +6,16 @@ import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import "@zetachain/toolkit/contracts/OnlySystem.sol"; -contract Multioutput is zContract, Ownable { +contract Multioutput is zContract, Ownable, OnlySystem { error NoAvailableTransfers(); error InvalidRecipient(); error FetchingBTCZRC20Failed(); event Withdrawal(address, uint256, bytes); - SystemContract public immutable systemContract; + SystemContract public systemContract; uint256 constant BITCOIN = 18332; @@ -22,22 +23,14 @@ contract Multioutput is zContract, Ownable { systemContract = SystemContract(systemContractAddress); } - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - function onCrossChainCall( zContext calldata context, address zrc20, uint256 amount, bytes calldata message - ) external virtual override onlySystem { - address btcToken = systemContract.gasCoinZRC20ByChainId(BITCOIN); - if (btcToken == address(0)) revert FetchingBTCZRC20Failed(); + ) external virtual override onlySystem(systemContract) { + if (systemContract.gasCoinZRC20ByChainId(BITCOIN) == address(0)) + revert FetchingBTCZRC20Failed(); ( address evmRecipient, @@ -69,7 +62,7 @@ contract Multioutput is zContract, Ownable { BytesHelperLib.addressToBytes(evmRecipient) ); - if (targetZRC20 == btcToken) { + if (targetZRC20 == systemContract.gasCoinZRC20ByChainId(BITCOIN)) { if (btcRecipient.length == 0) revert InvalidRecipient(); recipient = abi.encodePacked(btcRecipient); } @@ -88,19 +81,15 @@ contract Multioutput is zContract, Ownable { .withdrawGasFee(); uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), + systemContract, zrc20, gasFee, gasZRC20, amountToTransfer ); - uint256 outputAmount = SwapHelperLib._doSwap( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), + uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens( + systemContract, zrc20, amountToTransfer - inputForGas, targetZRC20, diff --git a/omnichain/multioutput/package.json b/omnichain/multioutput/package.json index de6eff39..3c9ced6a 100644 --- a/omnichain/multioutput/package.json +++ b/omnichain/multioutput/package.json @@ -27,7 +27,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0-rc3", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", @@ -41,7 +41,7 @@ "eslint-plugin-sort-keys-fix": "^1.1.2", "eslint-plugin-typescript-sort-keys": "^2.3.0", "ethers": "^5.4.7", - "hardhat": "^2.14.0", + "hardhat": "^2.17.2", "hardhat-gas-reporter": "^1.0.8", "prettier": "^2.8.8", "solidity-coverage": "^0.8.0", @@ -49,4 +49,4 @@ "typechain": "^8.1.0", "typescript": ">=4.5.0" } -} +} \ No newline at end of file diff --git a/omnichain/multioutput/yarn.lock b/omnichain/multioutput/yarn.lock index 1ca227c8..e4366b2c 100644 --- a/omnichain/multioutput/yarn.lock +++ b/omnichain/multioutput/yarn.lock @@ -1039,6 +1039,54 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nomicfoundation/edr-darwin-arm64@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.7.tgz#c204edc79643624dbd431b489b254778817d8244" + integrity sha512-6tK9Lv/lSfyBvpEQ4nsTfgxyDT1y1Uv/x8Wa+aB+E8qGo3ToexQ1BMVjxJk6PChXCDOWxB3B4KhqaZFjdhl3Ow== + +"@nomicfoundation/edr-darwin-x64@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.7.tgz#c3b394445084270cc5250d6c1869b0574e7ef810" + integrity sha512-1RrQ/1JPwxrYO69e0tglFv5H+ggour5Ii3bb727+yBpBShrxtOTQ7fZyfxA5h62LCN+0Z9wYOPeQ7XFcVurMaQ== + +"@nomicfoundation/edr-linux-arm64-gnu@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.7.tgz#6d65545a44d1323bb7ab08c3306947165d2071de" + integrity sha512-ds/CKlBoVXIihjhflhgPn13EdKWed6r5bgvMs/YwRqT5wldQAQJZWAfA2+nYm0Yi2gMGh1RUpBcfkyl4pq7G+g== + +"@nomicfoundation/edr-linux-arm64-musl@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.7.tgz#5368534bceac1a8c18b1be6b908caca5d39b0c03" + integrity sha512-e29udiRaPujhLkM3+R6ju7QISrcyOqpcaxb2FsDWBkuD7H8uU9JPZEyyUIpEp5uIY0Jh1eEJPKZKIXQmQAEAuw== + +"@nomicfoundation/edr-linux-x64-gnu@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.7.tgz#42349bf5941dbb54a5719942924c6e4e8cde348e" + integrity sha512-/xkjmTyv+bbJ4akBCW0qzFKxPOV4AqLOmqurov+s9umHb16oOv72osSa3SdzJED2gHDaKmpMITT4crxbar4Axg== + +"@nomicfoundation/edr-linux-x64-musl@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.7.tgz#e6babe11c9a8012f1284e6e48c3551861f2a7cd4" + integrity sha512-QwBP9xlmsbf/ldZDGLcE4QiAb8Zt46E/+WLpxHBATFhGa7MrpJh6Zse+h2VlrT/SYLPbh2cpHgSmoSlqVxWG9g== + +"@nomicfoundation/edr-win32-x64-msvc@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.7.tgz#1504b98f305f03be153b0220a546985660de9dc6" + integrity sha512-j/80DEnkxrF2ewdbk/gQ2EOPvgF0XSsg8D0o4+6cKhUVAW6XwtWKzIphNL6dyD2YaWEPgIrNvqiJK/aln0ww4Q== + +"@nomicfoundation/edr@^0.3.5": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.3.7.tgz#9c75edf1fcf601617905b2c89acf103f4786d017" + integrity sha512-v2JFWnFKRsnOa6PDUrD+sr8amcdhxnG/YbL7LzmgRGU1odWEyOF4/EwNeUajQr4ZNKVWrYnJ6XjydXtUge5OBQ== + optionalDependencies: + "@nomicfoundation/edr-darwin-arm64" "0.3.7" + "@nomicfoundation/edr-darwin-x64" "0.3.7" + "@nomicfoundation/edr-linux-arm64-gnu" "0.3.7" + "@nomicfoundation/edr-linux-arm64-musl" "0.3.7" + "@nomicfoundation/edr-linux-x64-gnu" "0.3.7" + "@nomicfoundation/edr-linux-x64-musl" "0.3.7" + "@nomicfoundation/edr-win32-x64-msvc" "0.3.7" + "@nomicfoundation/ethereumjs-block@5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" @@ -1079,6 +1127,13 @@ "@nomicfoundation/ethereumjs-util" "9.0.1" crc-32 "^1.2.0" +"@nomicfoundation/ethereumjs-common@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb" + integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.4" + "@nomicfoundation/ethereumjs-ethash@3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" @@ -1110,6 +1165,11 @@ resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== +"@nomicfoundation/ethereumjs-rlp@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30" + integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw== + "@nomicfoundation/ethereumjs-statemanager@2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" @@ -1145,6 +1205,16 @@ "@nomicfoundation/ethereumjs-util" "9.0.1" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-tx@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da" + integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-util@9.0.1": version "9.0.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" @@ -1154,6 +1224,14 @@ "@nomicfoundation/ethereumjs-rlp" "5.0.1" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-util@9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38" + integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-vm@7.0.1": version "7.0.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" @@ -1721,10 +1799,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0-rc3": + version "8.0.0-rc3" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" + integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" @@ -1847,6 +1925,13 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" @@ -2198,6 +2283,20 @@ bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2332,7 +2431,7 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -2470,6 +2569,11 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cli-cursor@^3.0.0, cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -3964,7 +4068,7 @@ hardhat-gas-reporter@^1.0.8: eth-gas-reporter "^0.2.25" sha1 "^1.1.1" -hardhat@^2.14.0, hardhat@^2.15.0: +hardhat@^2.15.0: version "2.17.1" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.17.1.tgz#4b6c8c8f624fd23d9f40185a4af24815d05a486a" integrity sha512-1PxRkfjhEzXs/wDxI5YgzYBxNmvzifBTjYzuopwel+vXpAhCudplusJthN5eig0FTs4qbi828DBIITEDh8x9LA== @@ -4018,6 +4122,55 @@ hardhat@^2.14.0, hardhat@^2.15.0: uuid "^8.3.2" ws "^7.4.6" +hardhat@^2.17.2: + version "2.22.3" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.3.tgz#50605daca6b29862397e446c42ec14c89430bec3" + integrity sha512-k8JV2ECWNchD6ahkg2BR5wKVxY0OiKot7fuxiIpRK0frRqyOljcR2vKwgWSLw6YIeDcNNA4xybj7Og7NSxr2hA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/edr" "^0.3.5" + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-tx" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -5960,7 +6113,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6588,6 +6741,13 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + wif@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" diff --git a/omnichain/nft/contracts/NFT.sol b/omnichain/nft/contracts/NFT.sol index 4659b2ff..320fb1e3 100644 --- a/omnichain/nft/contracts/NFT.sol +++ b/omnichain/nft/contracts/NFT.sol @@ -5,11 +5,13 @@ import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; +import "@zetachain/toolkit/contracts/OnlySystem.sol"; -contract NFT is zContract, ERC721 { +contract NFT is zContract, ERC721, OnlySystem { + SystemContract public immutable systemContract; + error CallerNotOwnerNotApproved(); uint256 constant BITCOIN = 18332; - SystemContract public immutable systemContract; mapping(uint256 => uint256) public tokenAmounts; mapping(uint256 => uint256) public tokenChains; @@ -20,20 +22,12 @@ contract NFT is zContract, ERC721 { _nextTokenId = 0; } - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - function onCrossChainCall( zContext calldata context, address zrc20, uint256 amount, bytes calldata message - ) external override onlySystem { + ) external override onlySystem(systemContract) { address recipient; if (context.chainID == BITCOIN) { @@ -58,10 +52,9 @@ contract NFT is zContract, ERC721 { } function burnNFT(uint256 tokenId, bytes memory recipient) public { - require( - _isApprovedOrOwner(_msgSender(), tokenId), - "Caller is not owner nor approved" - ); + if (!_isApprovedOrOwner(_msgSender(), tokenId)) { + revert CallerNotOwnerNotApproved(); + } address zrc20 = systemContract.gasCoinZRC20ByChainId( tokenChains[tokenId] ); diff --git a/omnichain/nft/package.json b/omnichain/nft/package.json index 01eff927..84c73eb4 100644 --- a/omnichain/nft/package.json +++ b/omnichain/nft/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0-rc3", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/nft/yarn.lock b/omnichain/nft/yarn.lock index 91d25e6c..b878641a 100644 --- a/omnichain/nft/yarn.lock +++ b/omnichain/nft/yarn.lock @@ -1716,10 +1716,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0-rc3": + version "8.0.0-rc3" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" + integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/omnichain/staking/contracts/Staking.sol b/omnichain/staking/contracts/Staking.sol index 5ec2fce3..95b3b6ff 100644 --- a/omnichain/staking/contracts/Staking.sol +++ b/omnichain/staking/contracts/Staking.sol @@ -5,9 +5,10 @@ import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; +import "@zetachain/toolkit/contracts/OnlySystem.sol"; -contract Staking is ERC20, zContract { - SystemContract public immutable systemContract; +contract Staking is ERC20, zContract, OnlySystem { + SystemContract public systemContract; uint256 public immutable chainID; uint256 constant BITCOIN = 18332; @@ -35,20 +36,12 @@ contract Staking is ERC20, zContract { chainID = chainID_; } - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - function onCrossChainCall( zContext calldata context, address zrc20, uint256 amount, bytes calldata message - ) external virtual override onlySystem { + ) external virtual override onlySystem(systemContract) { if (chainID != context.chainID) { revert WrongChain(context.chainID); } diff --git a/omnichain/staking/package.json b/omnichain/staking/package.json index 01eff927..84c73eb4 100644 --- a/omnichain/staking/package.json +++ b/omnichain/staking/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0-rc3", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/staking/yarn.lock b/omnichain/staking/yarn.lock index 91d25e6c..b878641a 100644 --- a/omnichain/staking/yarn.lock +++ b/omnichain/staking/yarn.lock @@ -1716,10 +1716,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0-rc3": + version "8.0.0-rc3" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" + integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/omnichain/swap/contracts/Swap.sol b/omnichain/swap/contracts/Swap.sol index f74ff840..ade9faf8 100644 --- a/omnichain/swap/contracts/Swap.sol +++ b/omnichain/swap/contracts/Swap.sol @@ -5,8 +5,9 @@ import "@zetachain/protocol-contracts/contracts/zevm/SystemContract.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; +import "@zetachain/toolkit/contracts/OnlySystem.sol"; -contract Swap is zContract { +contract Swap is zContract, OnlySystem { SystemContract public systemContract; uint256 constant BITCOIN = 18332; @@ -14,36 +15,31 @@ contract Swap is zContract { systemContract = SystemContract(systemContractAddress); } - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - function onCrossChainCall( zContext calldata context, address zrc20, uint256 amount, bytes calldata message - ) external virtual override onlySystem { - address target; - bytes memory to; + ) external virtual override onlySystem(systemContract) { + address targetTokenAddress; + bytes memory recipientAddress; if (context.chainID == BITCOIN) { - target = BytesHelperLib.bytesToAddress(message, 0); - to = abi.encodePacked(BytesHelperLib.bytesToAddress(message, 20)); + targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); + recipientAddress = abi.encodePacked( + BytesHelperLib.bytesToAddress(message, 20) + ); } else { (address targetToken, bytes memory recipient) = abi.decode( message, (address, bytes) ); - target = targetToken; - to = recipient; + targetTokenAddress = targetToken; + recipientAddress = recipient; } - (address gasZRC20, uint256 gasFee) = IZRC20(target).withdrawGasFee(); + (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) + .withdrawGasFee(); uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( systemContract, @@ -57,11 +53,11 @@ contract Swap is zContract { systemContract, zrc20, amount - inputForGas, - target, + targetTokenAddress, 0 ); - IZRC20(gasZRC20).approve(target, gasFee); - IZRC20(target).withdraw(to, outputAmount); + IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); + IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); } } diff --git a/omnichain/swap/contracts/SwapToZeta.sol b/omnichain/swap/contracts/SwapToZeta.sol index 570b155f..f7a5513f 100644 --- a/omnichain/swap/contracts/SwapToZeta.sol +++ b/omnichain/swap/contracts/SwapToZeta.sol @@ -6,8 +6,9 @@ import "@zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol"; import "@zetachain/toolkit/contracts/SwapHelperLib.sol"; import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; import "@zetachain/protocol-contracts/contracts/zevm/interfaces/IWZETA.sol"; +import "@zetachain/toolkit/contracts/OnlySystem.sol"; -contract SwapToZeta is zContract { +contract SwapToZeta is zContract, OnlySystem { SystemContract public systemContract; uint256 constant BITCOIN = 18332; @@ -16,20 +17,12 @@ contract SwapToZeta is zContract { systemContract = SystemContract(systemContractAddress); } - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - function onCrossChainCall( zContext calldata context, address zrc20, uint256 amount, bytes calldata message - ) external virtual override onlySystem { + ) external virtual override onlySystem(systemContract) { address target; bytes memory to; diff --git a/omnichain/swap/package.json b/omnichain/swap/package.json index 031fd967..84c73eb4 100644 --- a/omnichain/swap/package.json +++ b/omnichain/swap/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "8.0.0-rc1", + "@zetachain/toolkit": "8.0.0-rc3", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/swap/yarn.lock b/omnichain/swap/yarn.lock index ad316b1b..3a4ff88e 100644 --- a/omnichain/swap/yarn.lock +++ b/omnichain/swap/yarn.lock @@ -1736,10 +1736,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@8.0.0-rc1": - version "8.0.0-rc1" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc1.tgz#f7ef34393e63a7e33c2e7b27c307b9423972151f" - integrity sha512-V0uqIQgfYDCg2Ni4ccy6Il3IdOjgOZ5nISTURidq4wocLDAPQHl0yoos9GoVqL5QYa49WLFFEL8lRXouU0qz3g== +"@zetachain/toolkit@8.0.0-rc3": + version "8.0.0-rc3" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" + integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/package.json b/package.json index 2ae266d9..5dbb89b4 100644 --- a/package.json +++ b/package.json @@ -8,5 +8,6 @@ ], "scripts": { "build": "sh scripts/build.sh" - } -} \ No newline at end of file + }, + "packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72" +} From ed5e6bb2809bd4d8d57cfe8ac5d6c22dd5d44dcb Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Tue, 14 May 2024 18:29:46 +0400 Subject: [PATCH 10/13] remove flat file --- omnichain/swap/flat | 2453 ------------------------------------------- 1 file changed, 2453 deletions(-) delete mode 100644 omnichain/swap/flat diff --git a/omnichain/swap/flat b/omnichain/swap/flat deleted file mode 100644 index bb67950c..00000000 --- a/omnichain/swap/flat +++ /dev/null @@ -1,2453 +0,0 @@ -// Sources flattened with hardhat v2.19.2 https://hardhat.org - -// SPDX-License-Identifier: MIT AND UNLICENSED - -// File @openzeppelin/contracts/token/ERC20/IERC20.sol@v4.9.6 - -// Original license: SPDX_License_Identifier: MIT -// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) - -pragma solidity ^0.8.0; - -/** - * @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 @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol@v4.9.6 - -// Original license: SPDX_License_Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Interface for the optional metadata functions from the ERC20 standard. - * - * _Available since v4.1._ - */ -interface IERC20Metadata is IERC20 { - /** - * @dev Returns the name of the token. - */ - function name() external view returns (string memory); - - /** - * @dev Returns the symbol of the token. - */ - function symbol() external view returns (string memory); - - /** - * @dev Returns the decimals places of the token. - */ - function decimals() external view returns (uint8); -} - - -// File @openzeppelin/contracts/utils/Context.sol@v4.9.6 - -// Original license: SPDX_License_Identifier: MIT -// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) - -pragma solidity ^0.8.0; - -/** - * @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; - } - - function _contextSuffixLength() internal view virtual returns (uint256) { - return 0; - } -} - - -// File @openzeppelin/contracts/token/ERC20/ERC20.sol@v4.9.6 - -// Original license: SPDX_License_Identifier: MIT -// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) - -pragma solidity ^0.8.0; - - - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * For a generic mechanism see {ERC20PresetMinterPauser}. - * - * TIP: For a detailed writeup see our guide - * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * The default value of {decimals} is 18. To change this, you should override - * this function so it returns a different value. - * - * We have followed general OpenZeppelin Contracts guidelines: functions revert - * instead returning `false` on failure. This behavior is nonetheless - * conventional and does not conflict with the expectations of ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. See {IERC20-approve}. - */ -contract ERC20 is Context, IERC20, IERC20Metadata { - mapping(address => uint256) private _balances; - - mapping(address => mapping(address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - - /** - * @dev Sets the values for {name} and {symbol}. - * - * All two of these values are immutable: they can only be set once during - * construction. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev Returns the name of the token. - */ - function name() public view virtual override returns (string memory) { - return _name; - } - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() public view virtual override returns (string memory) { - return _symbol; - } - - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5.05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the default value returned by this function, unless - * it's overridden. - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. - */ - function decimals() public view virtual override returns (uint8) { - return 18; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual override returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf(address account) public view virtual override returns (uint256) { - return _balances[account]; - } - - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - the caller must have a balance of at least `amount`. - */ - function transfer(address to, uint256 amount) public virtual override returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, amount); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on - * `transferFrom`. This is semantically equivalent to an infinite approval. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve(address spender, uint256 amount) public virtual override returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, amount); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * NOTE: Does not update the allowance if the current allowance - * is the maximum `uint256`. - * - * Requirements: - * - * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - * - the caller must have allowance for ``from``'s tokens of at least - * `amount`. - */ - function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { - address spender = _msgSender(); - _spendAllowance(from, spender, amount); - _transfer(from, to, amount); - return true; - } - - /** - * @dev Atomically increases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, allowance(owner, spender) + addedValue); - return true; - } - - /** - * @dev Atomically decreases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `spender` must have allowance for the caller of at least - * `subtractedValue`. - */ - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - address owner = _msgSender(); - uint256 currentAllowance = allowance(owner, spender); - require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); - unchecked { - _approve(owner, spender, currentAllowance - subtractedValue); - } - - return true; - } - - /** - * @dev Moves `amount` of tokens from `from` to `to`. - * - * This internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - */ - function _transfer(address from, address to, uint256 amount) internal virtual { - require(from != address(0), "ERC20: transfer from the zero address"); - require(to != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(from, to, amount); - - uint256 fromBalance = _balances[from]; - require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); - unchecked { - _balances[from] = fromBalance - amount; - // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by - // decrementing then incrementing. - _balances[to] += amount; - } - - emit Transfer(from, to, amount); - - _afterTokenTransfer(from, to, amount); - } - - /** @dev Creates `amount` tokens and assigns them to `account`, increasing - * the total supply. - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - */ - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply += amount; - unchecked { - // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. - _balances[account] += amount; - } - emit Transfer(address(0), account, amount); - - _afterTokenTransfer(address(0), account, amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, reducing the - * total supply. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - * - `account` must have at least `amount` tokens. - */ - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - uint256 accountBalance = _balances[account]; - require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); - unchecked { - _balances[account] = accountBalance - amount; - // Overflow not possible: amount <= accountBalance <= totalSupply. - _totalSupply -= amount; - } - - emit Transfer(account, address(0), amount); - - _afterTokenTransfer(account, address(0), amount); - } - - /** - * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. - * - * This internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - */ - 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); - } - - /** - * @dev Updates `owner` s allowance for `spender` based on spent `amount`. - * - * Does not update the allowance amount in case of infinite allowance. - * Revert if not enough allowance is available. - * - * Might emit an {Approval} event. - */ - function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { - uint256 currentAllowance = allowance(owner, spender); - if (currentAllowance != type(uint256).max) { - require(currentAllowance >= amount, "ERC20: insufficient allowance"); - unchecked { - _approve(owner, spender, currentAllowance - amount); - } - } - } - - /** - * @dev Hook that is called before any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * will be transferred to `to`. - * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} - - /** - * @dev Hook that is called after any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * has been transferred to `to`. - * - when `from` is zero, `amount` tokens have been minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens have been burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} -} - - -// File @uniswap/v2-core/contracts/interfaces/IUniswapV2ERC20.sol@v1.0.0 - -pragma solidity >=0.5.0; - -interface IUniswapV2ERC20 { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external pure returns (string memory); - function symbol() external pure returns (string memory); - function decimals() external pure returns (uint8); - function totalSupply() external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint value) external returns (bool); - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); - - function DOMAIN_SEPARATOR() external view returns (bytes32); - function PERMIT_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint); - - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; -} - - -// File @uniswap/v2-core/contracts/libraries/SafeMath.sol@v1.0.0 - -pragma solidity =0.5.16; - -// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) - -library SafeMath { - function add(uint x, uint y) internal pure returns (uint z) { - require((z = x + y) >= x, 'ds-math-add-overflow'); - } - - function sub(uint x, uint y) internal pure returns (uint z) { - require((z = x - y) <= x, 'ds-math-sub-underflow'); - } - - function mul(uint x, uint y) internal pure returns (uint z) { - require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); - } -} - - -// File @uniswap/v2-core/contracts/UniswapV2ERC20.sol@v1.0.0 - -pragma solidity =0.5.16; - - -contract UniswapV2ERC20 is IUniswapV2ERC20 { - using SafeMath for uint; - - string public constant name = 'Uniswap V2'; - string public constant symbol = 'UNI-V2'; - uint8 public constant decimals = 18; - uint public totalSupply; - mapping(address => uint) public balanceOf; - mapping(address => mapping(address => uint)) public allowance; - - bytes32 public DOMAIN_SEPARATOR; - // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - mapping(address => uint) public nonces; - - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - constructor() public { - uint chainId; - assembly { - chainId := chainid - } - DOMAIN_SEPARATOR = keccak256( - abi.encode( - keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), - keccak256(bytes(name)), - keccak256(bytes('1')), - chainId, - address(this) - ) - ); - } - - function _mint(address to, uint value) internal { - totalSupply = totalSupply.add(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(address(0), to, value); - } - - function _burn(address from, uint value) internal { - balanceOf[from] = balanceOf[from].sub(value); - totalSupply = totalSupply.sub(value); - emit Transfer(from, address(0), value); - } - - function _approve(address owner, address spender, uint value) private { - allowance[owner][spender] = value; - emit Approval(owner, spender, value); - } - - function _transfer(address from, address to, uint value) private { - balanceOf[from] = balanceOf[from].sub(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(from, to, value); - } - - function approve(address spender, uint value) external returns (bool) { - _approve(msg.sender, spender, value); - return true; - } - - function transfer(address to, uint value) external returns (bool) { - _transfer(msg.sender, to, value); - return true; - } - - function transferFrom(address from, address to, uint value) external returns (bool) { - if (allowance[from][msg.sender] != uint(-1)) { - allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); - } - _transfer(from, to, value); - return true; - } - - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { - require(deadline >= block.timestamp, 'UniswapV2: EXPIRED'); - bytes32 digest = keccak256( - abi.encodePacked( - '\x19\x01', - DOMAIN_SEPARATOR, - keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) - ) - ); - address recoveredAddress = ecrecover(digest, v, r, s); - require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE'); - _approve(owner, spender, value); - } -} - - -// File @uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol@v1.0.0 - -pragma solidity >=0.5.0; - -interface IUniswapV2Factory { - event PairCreated(address indexed token0, address indexed token1, address pair, uint); - - function feeTo() external view returns (address); - function feeToSetter() external view returns (address); - - function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint) external view returns (address pair); - function allPairsLength() external view returns (uint); - - function createPair(address tokenA, address tokenB) external returns (address pair); - - function setFeeTo(address) external; - function setFeeToSetter(address) external; -} - - -// File @uniswap/v2-core/contracts/interfaces/IERC20.sol@v1.0.0 - -pragma solidity >=0.5.0; - -interface IERC20 { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external view returns (string memory); - function symbol() external view returns (string memory); - function decimals() external view returns (uint8); - function totalSupply() external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint value) external returns (bool); - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); -} - - -// File @uniswap/v2-core/contracts/interfaces/IUniswapV2Callee.sol@v1.0.0 - -pragma solidity >=0.5.0; - -interface IUniswapV2Callee { - function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; -} - - -// File @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol@v1.0.0 - -pragma solidity >=0.5.0; - -interface IUniswapV2Pair { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external pure returns (string memory); - function symbol() external pure returns (string memory); - function decimals() external pure returns (uint8); - function totalSupply() external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint value) external returns (bool); - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); - - function DOMAIN_SEPARATOR() external view returns (bytes32); - function PERMIT_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint); - - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; - - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); - event Swap( - address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - function MINIMUM_LIQUIDITY() external pure returns (uint); - function factory() external view returns (address); - function token0() external view returns (address); - function token1() external view returns (address); - function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); - function price0CumulativeLast() external view returns (uint); - function price1CumulativeLast() external view returns (uint); - function kLast() external view returns (uint); - - function mint(address to) external returns (uint liquidity); - function burn(address to) external returns (uint amount0, uint amount1); - function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; - function skim(address to) external; - function sync() external; - - function initialize(address, address) external; -} - - -// File @uniswap/v2-core/contracts/libraries/Math.sol@v1.0.0 - -pragma solidity =0.5.16; - -// a library for performing various math operations - -library Math { - function min(uint x, uint y) internal pure returns (uint z) { - z = x < y ? x : y; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrt(uint y) internal pure returns (uint z) { - if (y > 3) { - z = y; - uint x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - } -} - - -// File @uniswap/v2-core/contracts/libraries/UQ112x112.sol@v1.0.0 - -pragma solidity =0.5.16; - -// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) - -// range: [0, 2**112 - 1] -// resolution: 1 / 2**112 - -library UQ112x112 { - uint224 constant Q112 = 2**112; - - // encode a uint112 as a UQ112x112 - function encode(uint112 y) internal pure returns (uint224 z) { - z = uint224(y) * Q112; // never overflows - } - - // divide a UQ112x112 by a uint112, returning a UQ112x112 - function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { - z = x / uint224(y); - } -} - - -// File @uniswap/v2-core/contracts/UniswapV2Pair.sol@v1.0.0 - -pragma solidity =0.5.16; - - - - - - - -contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { - using SafeMath for uint; - using UQ112x112 for uint224; - - uint public constant MINIMUM_LIQUIDITY = 10**3; - bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); - - address public factory; - address public token0; - address public token1; - - uint112 private reserve0; // uses single storage slot, accessible via getReserves - uint112 private reserve1; // uses single storage slot, accessible via getReserves - uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves - - uint public price0CumulativeLast; - uint public price1CumulativeLast; - uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event - - uint private unlocked = 1; - modifier lock() { - require(unlocked == 1, 'UniswapV2: LOCKED'); - unlocked = 0; - _; - unlocked = 1; - } - - function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { - _reserve0 = reserve0; - _reserve1 = reserve1; - _blockTimestampLast = blockTimestampLast; - } - - function _safeTransfer(address token, address to, uint value) private { - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED'); - } - - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); - event Swap( - address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - constructor() public { - factory = msg.sender; - } - - // called once by the factory at time of deployment - function initialize(address _token0, address _token1) external { - require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check - token0 = _token0; - token1 = _token1; - } - - // update reserves and, on the first call per block, price accumulators - function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { - require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW'); - uint32 blockTimestamp = uint32(block.timestamp % 2**32); - uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired - if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { - // * never overflows, and + overflow is desired - price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; - price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; - } - reserve0 = uint112(balance0); - reserve1 = uint112(balance1); - blockTimestampLast = blockTimestamp; - emit Sync(reserve0, reserve1); - } - - // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) - function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { - address feeTo = IUniswapV2Factory(factory).feeTo(); - feeOn = feeTo != address(0); - uint _kLast = kLast; // gas savings - if (feeOn) { - if (_kLast != 0) { - uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); - uint rootKLast = Math.sqrt(_kLast); - if (rootK > rootKLast) { - uint numerator = totalSupply.mul(rootK.sub(rootKLast)); - uint denominator = rootK.mul(5).add(rootKLast); - uint liquidity = numerator / denominator; - if (liquidity > 0) _mint(feeTo, liquidity); - } - } - } else if (_kLast != 0) { - kLast = 0; - } - } - - // this low-level function should be called from a contract which performs important safety checks - function mint(address to) external lock returns (uint liquidity) { - (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings - uint balance0 = IERC20(token0).balanceOf(address(this)); - uint balance1 = IERC20(token1).balanceOf(address(this)); - uint amount0 = balance0.sub(_reserve0); - uint amount1 = balance1.sub(_reserve1); - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - if (_totalSupply == 0) { - liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); - _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens - } else { - liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1); - } - require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED'); - _mint(to, liquidity); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Mint(msg.sender, amount0, amount1); - } - - // this low-level function should be called from a contract which performs important safety checks - function burn(address to) external lock returns (uint amount0, uint amount1) { - (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - uint balance0 = IERC20(_token0).balanceOf(address(this)); - uint balance1 = IERC20(_token1).balanceOf(address(this)); - uint liquidity = balanceOf[address(this)]; - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution - amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution - require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED'); - _burn(address(this), liquidity); - _safeTransfer(_token0, to, amount0); - _safeTransfer(_token1, to, amount1); - balance0 = IERC20(_token0).balanceOf(address(this)); - balance1 = IERC20(_token1).balanceOf(address(this)); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Burn(msg.sender, amount0, amount1, to); - } - - // this low-level function should be called from a contract which performs important safety checks - function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { - require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT'); - (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings - require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY'); - - uint balance0; - uint balance1; - { // scope for _token{0,1}, avoids stack too deep errors - address _token0 = token0; - address _token1 = token1; - require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO'); - if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens - if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens - if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); - balance0 = IERC20(_token0).balanceOf(address(this)); - balance1 = IERC20(_token1).balanceOf(address(this)); - } - uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; - uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; - require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT'); - { // scope for reserve{0,1}Adjusted, avoids stack too deep errors - uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); - uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); - require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K'); - } - - _update(balance0, balance1, _reserve0, _reserve1); - emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); - } - - // force balances to match reserves - function skim(address to) external lock { - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0)); - _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1)); - } - - // force reserves to match balances - function sync() external lock { - _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1); - } -} - - -// File @uniswap/v2-core/contracts/UniswapV2Factory.sol@v1.0.0 - -pragma solidity =0.5.16; - - -contract UniswapV2Factory is IUniswapV2Factory { - address public feeTo; - address public feeToSetter; - - mapping(address => mapping(address => address)) public getPair; - address[] public allPairs; - - event PairCreated(address indexed token0, address indexed token1, address pair, uint); - - constructor(address _feeToSetter) public { - feeToSetter = _feeToSetter; - } - - function allPairsLength() external view returns (uint) { - return allPairs.length; - } - - function createPair(address tokenA, address tokenB) external returns (address pair) { - require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES'); - (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS'); - require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient - bytes memory bytecode = type(UniswapV2Pair).creationCode; - bytes32 salt = keccak256(abi.encodePacked(token0, token1)); - assembly { - pair := create2(0, add(bytecode, 32), mload(bytecode), salt) - } - IUniswapV2Pair(pair).initialize(token0, token1); - getPair[token0][token1] = pair; - getPair[token1][token0] = pair; // populate mapping in the reverse direction - allPairs.push(pair); - emit PairCreated(token0, token1, pair, allPairs.length); - } - - function setFeeTo(address _feeTo) external { - require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); - feeTo = _feeTo; - } - - function setFeeToSetter(address _feeToSetter) external { - require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); - feeToSetter = _feeToSetter; - } -} - - -// File @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol@v1.1.0-beta.0 - -pragma solidity >=0.6.2; - -interface IUniswapV2Router01 { - function factory() external pure returns (address); - function WETH() external pure returns (address); - - function addLiquidity( - address tokenA, - address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB, uint liquidity); - function addLiquidityETH( - address token, - uint amountTokenDesired, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external payable returns (uint amountToken, uint amountETH, uint liquidity); - function removeLiquidity( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB); - function removeLiquidityETH( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external returns (uint amountToken, uint amountETH); - function removeLiquidityWithPermit( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountA, uint amountB); - function removeLiquidityETHWithPermit( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountToken, uint amountETH); - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) - external - payable - returns (uint[] memory amounts); - function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) - external - returns (uint[] memory amounts); - function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) - external - returns (uint[] memory amounts); - function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) - external - payable - returns (uint[] memory amounts); - - function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); - function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); - function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); - function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); -} - - -// File @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol@v1.1.0-beta.0 - -pragma solidity >=0.6.2; - -interface IUniswapV2Router02 is IUniswapV2Router01 { - function removeLiquidityETHSupportingFeeOnTransferTokens( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external returns (uint amountETH); - function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountETH); - - function swapExactTokensForTokensSupportingFeeOnTransferTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external; - function swapExactETHForTokensSupportingFeeOnTransferTokens( - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external payable; - function swapExactTokensForETHSupportingFeeOnTransferTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external; -} - - -// File @zetachain/protocol-contracts/contracts/zevm/interfaces/IZRC20.sol@v7.0.0-rc1 - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.8.7; - -interface IZRC20 { - function totalSupply() external view returns (uint256); - - function balanceOf(address account) external view returns (uint256); - - function transfer(address recipient, uint256 amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint256); - - function approve(address spender, uint256 amount) external returns (bool); - - function decreaseAllowance(address spender, uint256 amount) external returns (bool); - - function increaseAllowance(address spender, uint256 amount) external returns (bool); - - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); - - function deposit(address to, uint256 amount) external returns (bool); - - function burn(address account, uint256 amount) external returns (bool); - - function withdraw(bytes memory to, uint256 amount) external returns (bool); - - function withdrawGasFee() external view returns (address, uint256); - - function PROTOCOL_FEE() external view returns (uint256); - - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); - event Deposit(bytes from, address indexed to, uint256 value); - event Withdrawal(address indexed from, bytes to, uint256 value, uint256 gasFee, uint256 protocolFlatFee); - event UpdatedSystemContract(address systemContract); - event UpdatedGasLimit(uint256 gasLimit); - event UpdatedProtocolFlatFee(uint256 protocolFlatFee); -} - - -// File @zetachain/protocol-contracts/contracts/zevm/interfaces/zContract.sol@v7.0.0-rc1 - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.8.7; - -struct zContext { - bytes origin; - address sender; - uint256 chainID; -} - -interface zContract { - function onCrossChainCall( - zContext calldata context, - address zrc20, - uint256 amount, - bytes calldata message - ) external; -} - - -// File @zetachain/protocol-contracts/contracts/zevm/SystemContract.sol@v7.0.0-rc1 - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.8.7; - - -/** - * @dev Custom errors for SystemContract - */ -interface SystemContractErrors { - error CallerIsNotFungibleModule(); - error InvalidTarget(); - error CantBeIdenticalAddresses(); - error CantBeZeroAddress(); - error ZeroAddress(); -} - -/** - * @dev The system contract it's called by the protocol to interact with the blockchain. - * Also includes a lot of tools to make easier to interact with ZetaChain. - */ -contract SystemContract is SystemContractErrors { - /// @notice Map to know the gas price of each chain given a chain id. - mapping(uint256 => uint256) public gasPriceByChainId; - /// @notice Map to know the ZRC20 address of a token given a chain id, ex zETH, zBNB etc. - mapping(uint256 => address) public gasCoinZRC20ByChainId; - // @dev: Map to know uniswap V2 pool of ZETA/ZRC20 given a chain id. This refer to the build in uniswap deployed at genesis. - mapping(uint256 => address) public gasZetaPoolByChainId; - - /// @notice Fungible address is always the same, it's on protocol level. - address public constant FUNGIBLE_MODULE_ADDRESS = 0x735b14BB79463307AAcBED86DAf3322B1e6226aB; - /// @notice Uniswap V2 addresses. - address public immutable uniswapv2FactoryAddress; - address public immutable uniswapv2Router02Address; - /// @notice Address of the wrapped ZETA to interact with Uniswap V2. - address public wZetaContractAddress; - /// @notice Address of ZEVM Zeta Connector. - address public zetaConnectorZEVMAddress; - - /// @notice Custom SystemContract errors. - event SystemContractDeployed(); - event SetGasPrice(uint256, uint256); - event SetGasCoin(uint256, address); - event SetGasZetaPool(uint256, address); - event SetWZeta(address); - event SetConnectorZEVM(address); - - /** - * @dev Only fungible module can deploy a system contract. - */ - constructor(address wzeta_, address uniswapv2Factory_, address uniswapv2Router02_) { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - wZetaContractAddress = wzeta_; - uniswapv2FactoryAddress = uniswapv2Factory_; - uniswapv2Router02Address = uniswapv2Router02_; - emit SystemContractDeployed(); - } - - /** - * @dev Deposit foreign coins into ZRC20 and call user specified contract on zEVM. - * @param context, context data for deposit. - * @param zrc20, zrc20 address for deposit. - * @param amount, amount to deposit. - * @param target, contract address to make a call after deposit. - * @param message, calldata for a call. - */ - function depositAndCall( - zContext calldata context, - address zrc20, - uint256 amount, - address target, - bytes calldata message - ) external { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - if (target == FUNGIBLE_MODULE_ADDRESS || target == address(this)) revert InvalidTarget(); - - IZRC20(zrc20).deposit(target, amount); - zContract(target).onCrossChainCall(context, zrc20, amount, message); - } - - /** - * @dev Sort token addresses lexicographically. Used to handle return values from pairs sorted in the order. - * @param tokenA, tokenA address. - * @param tokenB, tokenB address. - * @return token0 token1, returns sorted token addresses,. - */ - function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { - if (tokenA == tokenB) revert CantBeIdenticalAddresses(); - (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - if (token0 == address(0)) revert CantBeZeroAddress(); - } - - /** - * @dev Calculates the CREATE2 address for a pair without making any external calls. - * @param factory, factory address. - * @param tokenA, tokenA address. - * @param tokenB, tokenB address. - * @return pair tokens pair address. - */ - function uniswapv2PairFor(address factory, address tokenA, address tokenB) public pure returns (address pair) { - (address token0, address token1) = sortTokens(tokenA, tokenB); - pair = address( - uint160( - uint256( - keccak256( - abi.encodePacked( - hex"ff", - factory, - keccak256(abi.encodePacked(token0, token1)), - hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash - ) - ) - ) - ) - ); - } - - /** - * @dev Fungible module updates the gas price oracle periodically. - * @param chainID, chain id. - * @param price, new gas price. - */ - function setGasPrice(uint256 chainID, uint256 price) external { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - gasPriceByChainId[chainID] = price; - emit SetGasPrice(chainID, price); - } - - /** - * @dev Setter for gasCoinZRC20ByChainId map. - * @param chainID, chain id. - * @param zrc20, ZRC20 address. - */ - function setGasCoinZRC20(uint256 chainID, address zrc20) external { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - gasCoinZRC20ByChainId[chainID] = zrc20; - emit SetGasCoin(chainID, zrc20); - } - - /** - * @dev Set the pool wzeta/erc20 address. - * @param chainID, chain id. - * @param erc20, pair for uniswap wzeta/erc20. - */ - function setGasZetaPool(uint256 chainID, address erc20) external { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - address pool = uniswapv2PairFor(uniswapv2FactoryAddress, wZetaContractAddress, erc20); - gasZetaPoolByChainId[chainID] = pool; - emit SetGasZetaPool(chainID, pool); - } - - /** - * @dev Setter for wrapped ZETA address. - * @param addr, wzeta new address. - */ - function setWZETAContractAddress(address addr) external { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - if (addr == address(0)) revert ZeroAddress(); - wZetaContractAddress = addr; - emit SetWZeta(wZetaContractAddress); - } - - /** - * @dev Setter for zetaConnector ZEVM Address - * @param addr, zeta connector new address. - */ - function setConnectorZEVMAddress(address addr) external { - if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert CallerIsNotFungibleModule(); - if (addr == address(0)) revert ZeroAddress(); - zetaConnectorZEVMAddress = addr; - emit SetConnectorZEVM(zetaConnectorZEVMAddress); - } -} - - -// File @zetachain/toolkit/contracts/SwapHelperLib.sol@v7.0.0 - -// Original license: SPDX_License_Identifier: UNLICENSED -pragma solidity =0.8.7; - - - - -library SwapHelperLib { - uint16 internal constant MAX_DEADLINE = 200; - - error WrongGasContract(); - - error NotEnoughToPayGasFee(); - - error CantBeIdenticalAddresses(); - - error CantBeZeroAddress(); - - // returns sorted token addresses, used to handle return values from pairs sorted in this order - function sortTokens( - address tokenA, - address tokenB - ) internal pure returns (address token0, address token1) { - if (tokenA == tokenB) revert CantBeIdenticalAddresses(); - (token0, token1) = tokenA < tokenB - ? (tokenA, tokenB) - : (tokenB, tokenA); - if (token0 == address(0)) revert CantBeZeroAddress(); - } - - // calculates the CREATE2 address for a pair without making any external calls - function uniswapv2PairFor( - address factory, - address tokenA, - address tokenB - ) public pure returns (address pair) { - (address token0, address token1) = sortTokens(tokenA, tokenB); - pair = address( - uint160( - uint256( - keccak256( - abi.encodePacked( - hex"ff", - factory, - keccak256(abi.encodePacked(token0, token1)), - hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash - ) - ) - ) - ) - ); - } - - function _doWithdrawal( - address targetZRC20, - uint256 amount, - bytes32 receipient - ) internal { - (address gasZRC20, uint256 gasFee) = IZRC20(targetZRC20) - .withdrawGasFee(); - - if (gasZRC20 != targetZRC20) revert WrongGasContract(); - if (gasFee >= amount) revert NotEnoughToPayGasFee(); - - IZRC20(targetZRC20).approve(targetZRC20, gasFee); - IZRC20(targetZRC20).withdraw( - abi.encodePacked(receipient), - amount - gasFee - ); - } - - function _existsPairPool( - address uniswapV2Factory, - address zrc20A, - address zrc20B - ) internal view returns (bool) { - address uniswapPool = uniswapv2PairFor( - uniswapV2Factory, - zrc20A, - zrc20B - ); - return - IZRC20(zrc20A).balanceOf(uniswapPool) > 0 && - IZRC20(zrc20B).balanceOf(uniswapPool) > 0; - } - - function _doSwap( - address zetaToken, - address uniswapV2Factory, - address uniswapV2Router, - address zrc20, - uint256 amount, - address targetZRC20, - uint256 minAmountOut - ) internal returns (uint256) { - bool existsPairPool = _existsPairPool( - uniswapV2Factory, - zrc20, - targetZRC20 - ); - - address[] memory path; - if (existsPairPool) { - path = new address[](2); - path[0] = zrc20; - path[1] = targetZRC20; - } else { - path = new address[](3); - path[0] = zrc20; - path[1] = zetaToken; - path[2] = targetZRC20; - } - - IZRC20(zrc20).approve(address(uniswapV2Router), amount); - uint256[] memory amounts = IUniswapV2Router01(uniswapV2Router) - .swapExactTokensForTokens( - amount, - minAmountOut, - path, - address(this), - block.timestamp + MAX_DEADLINE - ); - return amounts[path.length - 1]; - } - - function swapTokensForExactTokens( - address zetaToken, - address uniswapV2Factory, - address uniswapV2Router, - address zrc20, - uint256 amount, - address targetZRC20, - uint256 amountInMax - ) internal returns (uint256) { - bool existsPairPool = _existsPairPool( - uniswapV2Factory, - zrc20, - targetZRC20 - ); - - address[] memory path; - if (existsPairPool) { - path = new address[](2); - path[0] = zrc20; - path[1] = targetZRC20; - } else { - path = new address[](3); - path[0] = zrc20; - path[1] = zetaToken; - path[2] = targetZRC20; - } - - IZRC20(zrc20).approve(address(uniswapV2Router), amountInMax); - uint256[] memory amounts = IUniswapV2Router01(uniswapV2Router) - .swapTokensForExactTokens( - amount, - amountInMax, - path, - address(this), - block.timestamp + MAX_DEADLINE - ); - return amounts[0]; - } -} - - -// File contracts/shared/libraries/SafeMath.sol - -pragma solidity =0.6.6; - -// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) - -library SafeMath { - function add(uint x, uint y) internal pure returns (uint z) { - require((z = x + y) >= x, 'ds-math-add-overflow'); - } - - function sub(uint x, uint y) internal pure returns (uint z) { - require((z = x - y) <= x, 'ds-math-sub-underflow'); - } - - function mul(uint x, uint y) internal pure returns (uint z) { - require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); - } -} - - -// File contracts/shared/libraries/UniswapV2Library.sol - -pragma solidity >=0.5.0; - - -library UniswapV2Library { - using SafeMath for uint; - - // returns sorted token addresses, used to handle return values from pairs sorted in this order - function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { - require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES'); - (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS'); - } - - // calculates the CREATE2 address for a pair without making any external calls - function pairFor(address factory, address tokenA, address tokenB) internal view returns (address pair) { - // Not working - // (address token0, address token1) = sortTokens(tokenA, tokenB); - // pair = address(uint(keccak256(abi.encodePacked( - // hex'ff', - // factory, - // keccak256(abi.encodePacked(token0, token1)), - // hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash - // )))); - pair = IUniswapV2Factory(factory).getPair(tokenA, tokenB); - } - - // fetches and sorts the reserves for a pair - function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) { - (address token0,) = sortTokens(tokenA, tokenB); - (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves(); - (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); - } - - // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset - function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { - require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT'); - require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); - amountB = amountA.mul(reserveB) / reserveA; - } - - // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset - function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { - require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT'); - require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); - uint amountInWithFee = amountIn.mul(997); - uint numerator = amountInWithFee.mul(reserveOut); - uint denominator = reserveIn.mul(1000).add(amountInWithFee); - amountOut = numerator / denominator; - } - - // given an output amount of an asset and pair reserves, returns a required input amount of the other asset - function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { - require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT'); - require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); - uint numerator = reserveIn.mul(amountOut).mul(1000); - uint denominator = reserveOut.sub(amountOut).mul(997); - amountIn = (numerator / denominator).add(1); - } - - // performs chained getAmountOut calculations on any number of pairs - function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) { - require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); - amounts = new uint[](path.length); - amounts[0] = amountIn; - for (uint i; i < path.length - 1; i++) { - (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]); - amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); - } - } - - // performs chained getAmountIn calculations on any number of pairs - function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) { - require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); - amounts = new uint[](path.length); - amounts[amounts.length - 1] = amountOut; - for (uint i = path.length - 1; i > 0; i--) { - (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]); - amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); - } - } -} - - -// File contracts/shared/MockSystemContract.sol - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.8.7; - - -interface SystemContractErrors { - error CallerIsNotFungibleModule(); - - error InvalidTarget(); - - error CantBeIdenticalAddresses(); - - error CantBeZeroAddress(); -} - -contract MockSystemContract is SystemContractErrors { - error TransferFailed(); - - mapping(uint256 => uint256) public gasPriceByChainId; - mapping(uint256 => address) public gasCoinZRC20ByChainId; - mapping(uint256 => address) public gasZetaPoolByChainId; - - address public wZetaContractAddress; - address public immutable uniswapv2FactoryAddress; - address public immutable uniswapv2Router02Address; - - event SystemContractDeployed(); - event SetGasPrice(uint256, uint256); - event SetGasCoin(uint256, address); - event SetGasZetaPool(uint256, address); - event SetWZeta(address); - - constructor(address wzeta_, address uniswapv2Factory_, address uniswapv2Router02_) { - wZetaContractAddress = wzeta_; - uniswapv2FactoryAddress = uniswapv2Factory_; - uniswapv2Router02Address = uniswapv2Router02_; - emit SystemContractDeployed(); - } - - // fungible module updates the gas price oracle periodically - function setGasPrice(uint256 chainID, uint256 price) external { - gasPriceByChainId[chainID] = price; - emit SetGasPrice(chainID, price); - } - - function setGasCoinZRC20(uint256 chainID, address zrc20) external { - gasCoinZRC20ByChainId[chainID] = zrc20; - emit SetGasCoin(chainID, zrc20); - } - - function setWZETAContractAddress(address addr) external { - wZetaContractAddress = addr; - emit SetWZeta(wZetaContractAddress); - } - - // returns sorted token addresses, used to handle return values from pairs sorted in this order - function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { - if (tokenA == tokenB) revert CantBeIdenticalAddresses(); - (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - if (token0 == address(0)) revert CantBeZeroAddress(); - } - - function uniswapv2PairFor(address factory, address tokenA, address tokenB) public pure returns (address pair) { - (address token0, address token1) = sortTokens(tokenA, tokenB); - pair = address( - uint160( - uint256( - keccak256( - abi.encodePacked( - hex"ff", - factory, - keccak256(abi.encodePacked(token0, token1)), - hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash - ) - ) - ) - ) - ); - } - - function onCrossChainCall(uint256 chainID, address target, address zrc20, uint256 amount, bytes calldata message) external { - zContext memory context = zContext({sender: msg.sender, origin: "", chainID: chainID}); - bool transfer = IZRC20(zrc20).transfer(target, amount); - if (!transfer) revert TransferFailed(); - zContract(target).onCrossChainCall(context, zrc20, amount, message); - } -} - - -// File @zetachain/toolkit/contracts/BytesHelperLib.sol@v7.0.0 - -// Original license: SPDX_License_Identifier: UNLICENSED -pragma solidity =0.8.7; - -library BytesHelperLib { - function bytesToAddress( - bytes calldata data, - uint256 offset - ) internal pure returns (address output) { - bytes memory b = data[offset:offset + 20]; - assembly { - output := mload(add(b, 20)) - } - } - - function bytesMemoryToAddress( - bytes memory data, - uint256 offset - ) internal pure returns (address output) { - assembly { - output := mload(add(add(data, offset), 32)) - } - } - - function bytesToUint32( - bytes calldata data, - uint256 offset - ) internal pure returns (uint32 output) { - bytes memory b = data[offset:offset + 4]; - assembly { - output := mload(add(b, 4)) - } - } - - function addressToBytes( - address someAddress - ) internal pure returns (bytes32) { - return bytes32(uint256(uint160(someAddress))); - } - - function bytesToBech32Bytes( - bytes calldata data, - uint256 offset - ) internal pure returns (bytes memory) { - bytes memory bech32Bytes = new bytes(42); - for (uint i = 0; i < 42; i++) { - bech32Bytes[i] = data[i + offset]; - } - - return bech32Bytes; - } -} - - -// File contracts/shared/MockZRC20.sol - -// Original license: SPDX_License_Identifier: MIT -pragma solidity =0.8.7; - - - -contract MockZRC20 is ERC20 { - address public gasFeeAddress; - uint256 public gasFee; - - event Withdrawal(address indexed from, bytes to, uint256 value, uint256 gasfee, uint256 protocolFlatFee); - - constructor(uint256 initialSupply, string memory name, string memory symbol) ERC20(name, symbol) { - _mint(msg.sender, initialSupply * (10 ** uint256(decimals()))); - gasFeeAddress = address(this); - } - - function setGasFeeAddress(address gasFeeAddress_) external { - gasFeeAddress = gasFeeAddress_; - } - - function setGasFee(uint256 gasFee_) external { - gasFee = gasFee_; - } - - function deposit(address to, uint256 amount) external returns (bool) { - return true; - } - - function bytesToAddress(bytes calldata data, uint256 offset, uint256 size) public pure returns (address output) { - bytes memory b = data[offset:offset + size]; - assembly { - output := mload(add(b, size)) - } - } - - function withdraw(bytes calldata to, uint256 amount) external returns (bool) { - address toAddress; - if (to.length < 32) { - toAddress = BytesHelperLib.bytesToAddress(to, 0); - } else { - toAddress = BytesHelperLib.bytesToAddress(to, 12); - } - - emit Withdrawal(msg.sender, to, amount, gasFee, 0); - return transfer(toAddress, amount); - } - - function withdrawGasFee() external view returns (address, uint256) { - return (gasFeeAddress, gasFee); - } -} - - -// File contracts/shared/TestUniswapCore.sol - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.5.16; - -/** - * @dev Contracts that need to be compiled for testing purposes - */ - - -// File @uniswap/lib/contracts/libraries/TransferHelper.sol@v1.1.1 - -pragma solidity >=0.6.0; - -// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false -library TransferHelper { - function safeApprove(address token, address to, uint value) internal { - // bytes4(keccak256(bytes('approve(address,uint256)'))); - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); - } - - function safeTransfer(address token, address to, uint value) internal { - // bytes4(keccak256(bytes('transfer(address,uint256)'))); - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); - } - - function safeTransferFrom(address token, address from, address to, uint value) internal { - // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); - } - - function safeTransferETH(address to, uint value) internal { - (bool success,) = to.call{value:value}(new bytes(0)); - require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); - } -} - - -// File contracts/shared/interfaces/IERC20.sol - -pragma solidity >=0.5.0; - -interface IERC20 { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external view returns (string memory); - function symbol() external view returns (string memory); - function decimals() external view returns (uint8); - function totalSupply() external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint value) external returns (bool); - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); -} - - -// File contracts/shared/interfaces/IWETH.sol - -pragma solidity >=0.5.0; - -interface IWETH { - function deposit() external payable; - function transfer(address to, uint value) external returns (bool); - function withdraw(uint) external; -} - - -// File contracts/shared/TestUniswapRouter.sol - -pragma solidity =0.6.6; - - - - - -contract TestUniswapRouter { - using SafeMath for uint; - - address public immutable factory; - address public immutable WETH; - - modifier ensure(uint deadline) { - require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED'); - _; - } - - constructor(address _factory, address _WETH) public { - factory = _factory; - WETH = _WETH; - } - - receive() external payable { - assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract - } - - // **** ADD LIQUIDITY **** - function _addLiquidity( - address tokenA, - address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin - ) internal returns (uint amountA, uint amountB) { - // create the pair if it doesn't exist yet - if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) { - address pair = IUniswapV2Factory(factory).createPair(tokenA, tokenB); - } - - (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB); - if (reserveA == 0 && reserveB == 0) { - (amountA, amountB) = (amountADesired, amountBDesired); - } else { - uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB); - if (amountBOptimal <= amountBDesired) { - require(amountBOptimal >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); - (amountA, amountB) = (amountADesired, amountBOptimal); - } else { - uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA); - assert(amountAOptimal <= amountADesired); - require(amountAOptimal >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); - (amountA, amountB) = (amountAOptimal, amountBDesired); - } - } - } - function addLiquidity( - address tokenA, - address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) { - (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin); - address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); - TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA); - TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); - liquidity = IUniswapV2Pair(pair).mint(to); - } - function addLiquidityETH( - address token, - uint amountTokenDesired, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) { - (amountToken, amountETH) = _addLiquidity( - token, - WETH, - amountTokenDesired, - msg.value, - amountTokenMin, - amountETHMin - ); - address pair = UniswapV2Library.pairFor(factory, token, WETH); - TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); - IWETH(WETH).deposit{value: amountETH}(); - assert(IWETH(WETH).transfer(pair, amountETH)); - liquidity = IUniswapV2Pair(pair).mint(to); - // refund dust eth, if any - if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); - - } - - // **** REMOVE LIQUIDITY **** - function removeLiquidity( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) public ensure(deadline) returns (uint amountA, uint amountB) { - address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); - IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair - (uint amount0, uint amount1) = IUniswapV2Pair(pair).burn(to); - (address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB); - (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); - require(amountA >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); - require(amountB >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); - } - function removeLiquidityETH( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) public ensure(deadline) returns (uint amountToken, uint amountETH) { - (amountToken, amountETH) = removeLiquidity( - token, - WETH, - liquidity, - amountTokenMin, - amountETHMin, - address(this), - deadline - ); - TransferHelper.safeTransfer(token, to, amountToken); - IWETH(WETH).withdraw(amountETH); - TransferHelper.safeTransferETH(to, amountETH); - } - - // **** SWAP **** - // requires the initial amount to have already been sent to the first pair - function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual { - for (uint i; i < path.length - 1; i++) { - (address input, address output) = (path[i], path[i + 1]); - (address token0,) = UniswapV2Library.sortTokens(input, output); - uint amountOut = amounts[i + 1]; - (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0)); - address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to; - IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)).swap( - amount0Out, amount1Out, to, new bytes(0) - ); - } - } - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external ensure(deadline) returns (uint[] memory amounts) { - amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); - require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); - TransferHelper.safeTransferFrom( - path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] - ); - _swap(amounts, path, to); - } - function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address[] calldata path, - address to, - uint deadline - ) external ensure(deadline) returns (uint[] memory amounts) { - amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); - require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT'); - TransferHelper.safeTransferFrom( - path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] - ); - _swap(amounts, path, to); - } - - // **** LIBRARY FUNCTIONS **** - function quote(uint amountA, uint reserveA, uint reserveB) public pure returns (uint amountB) { - return UniswapV2Library.quote(amountA, reserveA, reserveB); - } - - function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) - public - pure - returns (uint amountOut) - { - return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); - } - - function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) - public - pure - returns (uint amountIn) - { - return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); - } - - function getAmountsOut(uint amountIn, address[] memory path) - public - view - returns (uint[] memory amounts) - { - return UniswapV2Library.getAmountsOut(factory, amountIn, path); - } - - function getAmountsIn(uint amountOut, address[] memory path) - public - view - returns (uint[] memory amounts) - { - return UniswapV2Library.getAmountsIn(factory, amountOut, path); - } -} - - -// File contracts/Swap.sol - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.8.7; - - - - -contract Swap is zContract { - SystemContract public immutable systemContract; - uint256 constant BITCOIN = 18332; - - constructor(address systemContractAddress) { - systemContract = SystemContract(systemContractAddress); - } - - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - - function onCrossChainCall( - zContext calldata context, - address zrc20, - uint256 amount, - bytes calldata message - ) external virtual override onlySystem { - address targetTokenAddress; - bytes memory recipientAddress; - - if (context.chainID == BITCOIN) { - targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); - recipientAddress = abi.encodePacked( - BytesHelperLib.bytesToAddress(message, 20) - ); - } else { - (address targetToken, bytes memory recipient) = abi.decode( - message, - (address, bytes) - ); - targetTokenAddress = targetToken; - recipientAddress = recipient; - } - - (address gasZRC20, uint256 gasFee) = IZRC20(targetTokenAddress) - .withdrawGasFee(); - - uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), - zrc20, - gasFee, - gasZRC20, - amount - ); - - uint256 outputAmount = SwapHelperLib._doSwap( - systemContract.wZetaContractAddress(), - systemContract.uniswapv2FactoryAddress(), - systemContract.uniswapv2Router02Address(), - zrc20, - amount - inputForGas, - targetTokenAddress, - 0 - ); - - IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); - IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); - } -} - - -// File contracts/SwapExtended.sol - -// Original license: SPDX_License_Identifier: MIT -pragma solidity 0.8.7; - - - - - -contract SwapExtended is zContract { - SystemContract public systemContract; - address public wzeta; - address public factory; - address public router; - - uint256 constant BITCOIN = 18332; - - constructor(address systemContractAddress) { - systemContract = SystemContract(systemContractAddress); - wzeta = systemContract.wZetaContractAddress(); - factory = systemContract.uniswapv2FactoryAddress(); - router = systemContract.uniswapv2Router02Address(); - } - - modifier onlySystem() { - require( - msg.sender == address(systemContract), - "Only system contract can call this function" - ); - _; - } - - function onCrossChainCall( - zContext calldata context, - address zrc20, - uint256 amount, - bytes calldata message - ) external virtual override onlySystem { - address targetTokenAddress; - bytes memory recipientAddress; - - if (context.chainID == BITCOIN) { - targetTokenAddress = BytesHelperLib.bytesToAddress(message, 0); - recipientAddress = abi.encodePacked( - BytesHelperLib.bytesToAddress(message, 20) - ); - } else { - (address targetToken, bytes memory recipient) = abi.decode( - message, - (address, bytes) - ); - targetTokenAddress = targetToken; - recipientAddress = recipient; - } - - bool isTargetZeta = targetTokenAddress == wzeta; - uint256 inputForGas; - address gasZRC20; - uint256 gasFee; - - if (!isTargetZeta) { - (gasZRC20, gasFee) = IZRC20(targetTokenAddress).withdrawGasFee(); - - inputForGas = SwapHelperLib.swapTokensForExactTokens( - wzeta, - factory, - router, - zrc20, - gasFee, - gasZRC20, - amount - ); - } - - uint256 outputAmount = SwapHelperLib._doSwap( - wzeta, - factory, - router, - zrc20, - isTargetZeta ? amount : amount - inputForGas, - targetTokenAddress, - 0 - ); - - if (!isTargetZeta) { - IZRC20(gasZRC20).approve(targetTokenAddress, gasFee); - IZRC20(targetTokenAddress).withdraw(recipientAddress, outputAmount); - } - } -} - - -// File contracts/shared/WZETA.sol - -pragma solidity ^0.4.18; - -contract WZETA { - string public name = "Wrapped Zeta"; - string public symbol = "WZETA"; - uint8 public decimals = 18; - - 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; - - function() public payable { - deposit(); - } - - function deposit() public payable { - balanceOf[msg.sender] += msg.value; - Deposit(msg.sender, msg.value); - } - - function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - msg.sender.transfer(wad); - Withdrawal(msg.sender, wad); - } - - function totalSupply() public view returns (uint) { - return this.balance; - } - - function approve(address guy, uint wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - 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] != uint(-1)) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - Transfer(src, dst, wad); - - return true; - } -} From ddd147beea98872fdb9319977f19a10aa4eca392 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Tue, 14 May 2024 18:31:14 +0400 Subject: [PATCH 11/13] v8.0.0 --- omnichain/multioutput/package.json | 4 ++-- omnichain/multioutput/yarn.lock | 8 ++++---- omnichain/nft/package.json | 2 +- omnichain/nft/yarn.lock | 8 ++++---- omnichain/staking/package.json | 2 +- omnichain/staking/yarn.lock | 8 ++++---- omnichain/swap/package.json | 2 +- omnichain/swap/yarn.lock | 8 ++++---- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/omnichain/multioutput/package.json b/omnichain/multioutput/package.json index 3c9ced6a..6a65ce83 100644 --- a/omnichain/multioutput/package.json +++ b/omnichain/multioutput/package.json @@ -27,7 +27,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "8.0.0-rc3", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", @@ -49,4 +49,4 @@ "typechain": "^8.1.0", "typescript": ">=4.5.0" } -} \ No newline at end of file +} diff --git a/omnichain/multioutput/yarn.lock b/omnichain/multioutput/yarn.lock index e4366b2c..d9f57722 100644 --- a/omnichain/multioutput/yarn.lock +++ b/omnichain/multioutput/yarn.lock @@ -1799,10 +1799,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@8.0.0-rc3": - version "8.0.0-rc3" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" - integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/omnichain/nft/package.json b/omnichain/nft/package.json index 84c73eb4..533af220 100644 --- a/omnichain/nft/package.json +++ b/omnichain/nft/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "8.0.0-rc3", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/nft/yarn.lock b/omnichain/nft/yarn.lock index b878641a..e24efda9 100644 --- a/omnichain/nft/yarn.lock +++ b/omnichain/nft/yarn.lock @@ -1716,10 +1716,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@8.0.0-rc3": - version "8.0.0-rc3" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" - integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/omnichain/staking/package.json b/omnichain/staking/package.json index 84c73eb4..533af220 100644 --- a/omnichain/staking/package.json +++ b/omnichain/staking/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "8.0.0-rc3", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/staking/yarn.lock b/omnichain/staking/yarn.lock index b878641a..e24efda9 100644 --- a/omnichain/staking/yarn.lock +++ b/omnichain/staking/yarn.lock @@ -1716,10 +1716,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@8.0.0-rc3": - version "8.0.0-rc3" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" - integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/omnichain/swap/package.json b/omnichain/swap/package.json index 84c73eb4..533af220 100644 --- a/omnichain/swap/package.json +++ b/omnichain/swap/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "8.0.0-rc3", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/omnichain/swap/yarn.lock b/omnichain/swap/yarn.lock index 3a4ff88e..0cddf9e0 100644 --- a/omnichain/swap/yarn.lock +++ b/omnichain/swap/yarn.lock @@ -1736,10 +1736,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@8.0.0-rc3": - version "8.0.0-rc3" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0-rc3.tgz#b97a23bf0c438ce0f610f26c578a9ed3270d95f8" - integrity sha512-K0VKqoAN8WGA5/+DbGaB2oyN34wOt07no8OvBLUoyiuh/bLYvwsgnnAHoTpooV/K/gJVgaelkFiuNRbRt6vjgg== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" From b9d14112f8d0016e2d2b3f1359a913a43b3a2adc Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Tue, 14 May 2024 18:33:43 +0400 Subject: [PATCH 12/13] ccm v8.0.0 --- messaging/erc20/package.json | 2 +- messaging/erc20/yarn.lock | 8 ++++---- messaging/message/package.json | 2 +- messaging/message/yarn.lock | 8 ++++---- messaging/nft/package.json | 2 +- messaging/nft/yarn.lock | 8 ++++---- messaging/zeta/package.json | 2 +- messaging/zeta/yarn.lock | 8 ++++---- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/messaging/erc20/package.json b/messaging/erc20/package.json index 01eff927..533af220 100644 --- a/messaging/erc20/package.json +++ b/messaging/erc20/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/messaging/erc20/yarn.lock b/messaging/erc20/yarn.lock index 5adafe6f..62383860 100644 --- a/messaging/erc20/yarn.lock +++ b/messaging/erc20/yarn.lock @@ -1711,10 +1711,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/messaging/message/package.json b/messaging/message/package.json index 01eff927..533af220 100644 --- a/messaging/message/package.json +++ b/messaging/message/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/messaging/message/yarn.lock b/messaging/message/yarn.lock index 5adafe6f..62383860 100644 --- a/messaging/message/yarn.lock +++ b/messaging/message/yarn.lock @@ -1711,10 +1711,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/messaging/nft/package.json b/messaging/nft/package.json index 01eff927..533af220 100644 --- a/messaging/nft/package.json +++ b/messaging/nft/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/messaging/nft/yarn.lock b/messaging/nft/yarn.lock index 5adafe6f..62383860 100644 --- a/messaging/nft/yarn.lock +++ b/messaging/nft/yarn.lock @@ -1711,10 +1711,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" diff --git a/messaging/zeta/package.json b/messaging/zeta/package.json index 01eff927..533af220 100644 --- a/messaging/zeta/package.json +++ b/messaging/zeta/package.json @@ -26,7 +26,7 @@ "@types/node": ">=12.0.0", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", - "@zetachain/toolkit": "7.0.0", + "@zetachain/toolkit": "8.0.0", "axios": "^1.3.6", "chai": "^4.2.0", "dotenv": "^16.0.3", diff --git a/messaging/zeta/yarn.lock b/messaging/zeta/yarn.lock index 5adafe6f..62383860 100644 --- a/messaging/zeta/yarn.lock +++ b/messaging/zeta/yarn.lock @@ -1711,10 +1711,10 @@ resolved "https://registry.yarnpkg.com/@zetachain/protocol-contracts/-/protocol-contracts-7.0.0-rc1.tgz#588483d1ec70e572b7e40e84ef5b34282b0ab375" integrity sha512-vgS+Pjh4MysOyw8WbqTQVBsHJYqKvMcdV7cNVqxaTJd/dl2ak7NNvsIeaeUnxQrp8XfQol2B8GXJpVLM6MK/dg== -"@zetachain/toolkit@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-7.0.0.tgz#7301ccab40c37d3fd8fcc347f99c831ec31b1bd3" - integrity sha512-5cOJVBIEcosF2A2TJbNGFfh4Bob8UcodQII1RdHRstqvV3toZ18r1gVWpLGQ8w2N6T2FCPE8ueN4Q5zH68q20Q== +"@zetachain/toolkit@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@zetachain/toolkit/-/toolkit-8.0.0.tgz#e8a582104a84b649b54a9e230d9be44aebc1399f" + integrity sha512-PZ6emUAvypDuU0gCFMFh7UfsBeSwTi2E0zt2is2ezjdQ00OyMWDE2T5pMTvib6EDV5bquONfmJG4rExdx8+gEg== dependencies: "@inquirer/prompts" "^2.1.1" "@inquirer/select" "1.1.3" From b4084d5ca00ef84bd7b5b8cdf09099726fc55c5e Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Tue, 14 May 2024 21:58:07 +0400 Subject: [PATCH 13/13] remove immutable from nft contract --- omnichain/nft/contracts/NFT.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnichain/nft/contracts/NFT.sol b/omnichain/nft/contracts/NFT.sol index 320fb1e3..46d5820f 100644 --- a/omnichain/nft/contracts/NFT.sol +++ b/omnichain/nft/contracts/NFT.sol @@ -8,7 +8,7 @@ import "@zetachain/toolkit/contracts/BytesHelperLib.sol"; import "@zetachain/toolkit/contracts/OnlySystem.sol"; contract NFT is zContract, ERC721, OnlySystem { - SystemContract public immutable systemContract; + SystemContract public systemContract; error CallerNotOwnerNotApproved(); uint256 constant BITCOIN = 18332;