Skip to content

Commit

Permalink
conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
lumtis committed Jun 18, 2024
2 parents 6818fad + 94d6e4e commit a20a80f
Show file tree
Hide file tree
Showing 133 changed files with 12,376 additions and 354 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ cache
dist
node_modules
typechain-types
docs
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @andresaiello @brewmaster012 @lumtis @charliemc0 @fadeev
* @andresaiello @brewmaster012 @lumtis @charliemc0 @fadeev @skosito
1 change: 0 additions & 1 deletion contracts/evm/tools/ZetaInteractor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ abstract contract ZetaInteractor is Ownable2Step, ZetaInteractorErrors {
modifier isValidRevertCall(ZetaInterfaces.ZetaRevert calldata zetaRevert) {
_isValidCaller();
if (zetaRevert.zetaTxSenderAddress != address(this)) revert InvalidZetaRevertCall();
if (zetaRevert.sourceChainId != currentChainId) revert InvalidZetaRevertCall();
_;
}

Expand Down
149 changes: 149 additions & 0 deletions contracts/evm/tools/ZetaTokenConsumerZEVM.strategy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";

import "../interfaces/ZetaInterfaces.sol";
import "../../zevm/interfaces/IWZETA.sol";

interface ZetaTokenConsumerZEVMErrors {
error InputCantBeZero();

error ErrorSendingETH();

error ReentrancyError();

error NotEnoughValue();

error InputCantBeZeta();

error OutputCantBeZeta();

error OnlyWZETAAllowed();

error InvalidForZEVM();
}

/**
* @dev ZetaTokenConsumer for ZEVM
*/
contract ZetaTokenConsumerZEVM is ZetaTokenConsumer, ZetaTokenConsumerZEVMErrors {
using SafeERC20 for IERC20;
uint256 internal constant MAX_DEADLINE = 200;

address public immutable WETH9Address;

IUniswapV2Router02 internal immutable uniswapV2Router;

constructor(address WETH9Address_, address uniswapV2Router_) {
if (WETH9Address_ == address(0) || uniswapV2Router_ == address(0)) revert ZetaCommonErrors.InvalidAddress();

WETH9Address = WETH9Address_;
uniswapV2Router = IUniswapV2Router02(uniswapV2Router_);
}

function getZetaFromEth(
address destinationAddress,
uint256 minAmountOut
) external payable override returns (uint256) {
if (destinationAddress == address(0)) revert ZetaCommonErrors.InvalidAddress();
if (msg.value == 0) revert InputCantBeZero();
if (msg.value < minAmountOut) revert NotEnoughValue();

IWETH9(WETH9Address).deposit{value: msg.value}();
IERC20(WETH9Address).safeTransfer(destinationAddress, msg.value);
emit EthExchangedForZeta(msg.value, msg.value);
return msg.value;
}

function getZetaFromToken(
address destinationAddress,
uint256 minAmountOut,
address inputToken,
uint256 inputTokenAmount
) external override returns (uint256) {
if (destinationAddress == address(0) || inputToken == address(0)) revert ZetaCommonErrors.InvalidAddress();
if (inputTokenAmount == 0) revert InputCantBeZero();
if (inputToken == WETH9Address) revert InputCantBeZeta();

IERC20(inputToken).safeTransferFrom(msg.sender, address(this), inputTokenAmount);
IERC20(inputToken).safeApprove(address(uniswapV2Router), inputTokenAmount);

address[] memory path = new address[](2);
path[0] = inputToken;
path[1] = WETH9Address;

uint256[] memory amounts = uniswapV2Router.swapExactTokensForTokens(
inputTokenAmount,
minAmountOut,
path,
destinationAddress,
block.timestamp + MAX_DEADLINE
);
uint256 amountOut = amounts[path.length - 1];

emit TokenExchangedForZeta(inputToken, inputTokenAmount, amountOut);
return amountOut;
}

function getEthFromZeta(
address destinationAddress,
uint256 minAmountOut,
uint256 zetaTokenAmount
) external override returns (uint256) {
if (destinationAddress == address(0)) revert ZetaCommonErrors.InvalidAddress();
if (zetaTokenAmount == 0) revert InputCantBeZero();
if (zetaTokenAmount < minAmountOut) revert NotEnoughValue();

IERC20(WETH9Address).safeTransferFrom(msg.sender, address(this), zetaTokenAmount);
IWETH9(WETH9Address).withdraw(zetaTokenAmount);

emit ZetaExchangedForEth(zetaTokenAmount, zetaTokenAmount);

(bool sent, ) = destinationAddress.call{value: zetaTokenAmount}("");
if (!sent) revert ErrorSendingETH();

return zetaTokenAmount;
}

function getTokenFromZeta(
address destinationAddress,
uint256 minAmountOut,
address outputToken,
uint256 zetaTokenAmount
) external override returns (uint256) {
if (destinationAddress == address(0) || outputToken == address(0)) revert ZetaCommonErrors.InvalidAddress();
if (zetaTokenAmount == 0) revert InputCantBeZero();
if (outputToken == WETH9Address) revert OutputCantBeZeta();

IERC20(WETH9Address).safeTransferFrom(msg.sender, address(this), zetaTokenAmount);
IERC20(WETH9Address).safeApprove(address(uniswapV2Router), zetaTokenAmount);

address[] memory path = new address[](2);
path[0] = WETH9Address;
path[1] = outputToken;

uint256[] memory amounts = uniswapV2Router.swapExactTokensForTokens(
zetaTokenAmount,
minAmountOut,
path,
destinationAddress,
block.timestamp + MAX_DEADLINE
);

uint256 amountOut = amounts[path.length - 1];

emit ZetaExchangedForToken(outputToken, zetaTokenAmount, amountOut);
return amountOut;
}

function hasZetaLiquidity() external view override returns (bool) {
revert InvalidForZEVM();
}

receive() external payable {
if (msg.sender != WETH9Address) revert OnlyWZETAAllowed();
}
}
137 changes: 120 additions & 17 deletions contracts/zevm/ZetaConnectorZEVM.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "./interfaces/IWZETA.sol";

interface ZetaInterfaces {
/**
Expand Down Expand Up @@ -46,23 +47,34 @@ interface ZetaInterfaces {
}
}

interface WZETA {
function transferFrom(address src, address dst, uint wad) external returns (bool);
interface ZetaReceiver {
/**
* @dev onZetaMessage is called when a cross-chain message reaches a contract
*/
function onZetaMessage(ZetaInterfaces.ZetaMessage calldata zetaMessage) external;

function withdraw(uint wad) external;
/**
* @dev onZetaRevert is called when a cross-chain message reverts.
* It's useful to rollback to the original state
*/
function onZetaRevert(ZetaInterfaces.ZetaRevert calldata zetaRevert) external;
}

contract ZetaConnectorZEVM is ZetaInterfaces {
contract ZetaConnectorZEVM {
/// @notice WZETA token address.
address public wzeta;

/// @notice Contract custom errors.
error OnlyWZETA();
error OnlyWZETAOrFungible();
error WZETATransferFailed();
error OnlyFungibleModule();
error FailedZetaSent();
error WrongValue();

/// @notice Fungible module address.
address public constant FUNGIBLE_MODULE_ADDRESS = payable(0x735b14BB79463307AAcBED86DAf3322B1e6226aB);
/// @notice WZETA token address.
address public wzeta;

event SetWZETA(address wzeta_);

event ZetaSent(
address sourceTxOriginAddress,
Expand All @@ -74,15 +86,46 @@ contract ZetaConnectorZEVM is ZetaInterfaces {
bytes message,
bytes zetaParams
);
event SetWZETA(address wzeta_);

event ZetaReceived(
bytes zetaTxSenderAddress,
uint256 indexed sourceChainId,
address indexed destinationAddress,
uint256 zetaValue,
bytes message,
bytes32 indexed internalSendHash
);

event ZetaReverted(
address zetaTxSenderAddress,
uint256 sourceChainId,
uint256 indexed destinationChainId,
bytes destinationAddress,
uint256 remainingZetaValue,
bytes message,
bytes32 indexed internalSendHash
);

/**
* @dev Modifier to restrict actions to fungible module.
*/
modifier onlyFungibleModule() {
if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert OnlyFungibleModule();
_;
}

constructor(address wzeta_) {
wzeta = wzeta_;
}

/// @dev Receive function to receive ZETA from WETH9.withdraw().
receive() external payable {
if (msg.sender != wzeta) revert OnlyWZETA();
if (msg.sender != wzeta && msg.sender != FUNGIBLE_MODULE_ADDRESS) revert OnlyWZETAOrFungible();
}

function setWzetaAddress(address wzeta_) external onlyFungibleModule {
wzeta = wzeta_;
emit SetWZETA(wzeta_);
}

/**
Expand All @@ -91,8 +134,8 @@ contract ZetaConnectorZEVM is ZetaInterfaces {
*/
function send(ZetaInterfaces.SendInput calldata input) external {
// Transfer wzeta to "fungible" module, which will be burnt by the protocol post processing via hooks.
if (!WZETA(wzeta).transferFrom(msg.sender, address(this), input.zetaValueAndGas)) revert WZETATransferFailed();
WZETA(wzeta).withdraw(input.zetaValueAndGas);
if (!IWETH9(wzeta).transferFrom(msg.sender, address(this), input.zetaValueAndGas)) revert WZETATransferFailed();
IWETH9(wzeta).withdraw(input.zetaValueAndGas);
(bool sent, ) = FUNGIBLE_MODULE_ADDRESS.call{value: input.zetaValueAndGas}("");
if (!sent) revert FailedZetaSent();
emit ZetaSent(
Expand All @@ -108,12 +151,72 @@ contract ZetaConnectorZEVM is ZetaInterfaces {
}

/**
* @dev Sends ZETA and bytes messages (to execute it) crosschain.
* @param wzeta_, new WZETA address.
* @dev Handler to receive data from other chain.
* This method can be called only by Fungible Module.
* Transfer the Zeta tokens to destination and calls onZetaMessage if it's needed.
* To perform the transfer wrap the new tokens
*/
function setWzetaAddress(address wzeta_) external {
if (msg.sender != FUNGIBLE_MODULE_ADDRESS) revert OnlyFungibleModule();
wzeta = wzeta_;
emit SetWZETA(wzeta_);
function onReceive(
bytes calldata zetaTxSenderAddress,
uint256 sourceChainId,
address destinationAddress,
uint256 zetaValue,
bytes calldata message,
bytes32 internalSendHash
) external payable onlyFungibleModule {
if (msg.value != zetaValue) revert WrongValue();
IWETH9(wzeta).deposit{value: zetaValue}();
if (!IWETH9(wzeta).transferFrom(address(this), destinationAddress, zetaValue)) revert WZETATransferFailed();

if (message.length > 0) {
ZetaReceiver(destinationAddress).onZetaMessage(
ZetaInterfaces.ZetaMessage(zetaTxSenderAddress, sourceChainId, destinationAddress, zetaValue, message)
);
}

emit ZetaReceived(zetaTxSenderAddress, sourceChainId, destinationAddress, zetaValue, message, internalSendHash);
}

/**
* @dev Handler to receive errors from other chain.
* This method can be called only by Fungible Module.
* Transfer the Zeta tokens to destination and calls onZetaRevert if it's needed.
*/
function onRevert(
address zetaTxSenderAddress,
uint256 sourceChainId,
bytes calldata destinationAddress,
uint256 destinationChainId,
uint256 remainingZetaValue,
bytes calldata message,
bytes32 internalSendHash
) external payable onlyFungibleModule {
if (msg.value != remainingZetaValue) revert WrongValue();
IWETH9(wzeta).deposit{value: remainingZetaValue}();
if (!IWETH9(wzeta).transferFrom(address(this), zetaTxSenderAddress, remainingZetaValue))
revert WZETATransferFailed();

if (message.length > 0) {
ZetaReceiver(zetaTxSenderAddress).onZetaRevert(
ZetaInterfaces.ZetaRevert(
zetaTxSenderAddress,
sourceChainId,
destinationAddress,
destinationChainId,
remainingZetaValue,
message
)
);
}

emit ZetaReverted(
zetaTxSenderAddress,
sourceChainId,
destinationChainId,
destinationAddress,
remainingZetaValue,
message,
internalSendHash
);
}
}
Loading

0 comments on commit a20a80f

Please sign in to comment.