diff --git a/examples/swap/contracts/Swap.sol b/examples/swap/contracts/Swap.sol index 5e405208..e16ce2d8 100644 --- a/examples/swap/contracts/Swap.sol +++ b/examples/swap/contracts/Swap.sol @@ -119,10 +119,14 @@ contract Swap is UniversalContract { context.revertMessage, (address, address) ); - uint256 out = handleGasAndSwap(context.asset, context.amount, zrc20); + uint256 outputAmount = handleGasAndSwap( + context.asset, + context.amount, + zrc20 + ); gateway.withdraw( abi.encodePacked(sender), - out, + outputAmount, zrc20, RevertOptions({ revertAddress: sender, @@ -134,13 +138,7 @@ contract Swap is UniversalContract { ); } - // // Fallback function that reverts - // fallback() external payable { - // revert("Fallback function triggered"); - // } + fallback() external payable {} - // // Receive function that reverts (for ETH transfers) - // receive() external payable { - // revert("ETH transfers not allowed"); - // } + receive() external payable {} } diff --git a/examples/swap/contracts/SwapToAnyToken.sol b/examples/swap/contracts/SwapToAnyToken.sol index d3022c99..b9fa2b30 100644 --- a/examples/swap/contracts/SwapToAnyToken.sol +++ b/examples/swap/contracts/SwapToAnyToken.sol @@ -69,42 +69,64 @@ contract SwapToAnyToken is UniversalContract { params.withdraw = withdrawFlag; } - swapAndWithdraw( - zrc20, - amount, - params.target, - params.to, - params.withdraw - ); + ( + uint256 outputAmount, + address gasZRC20, + uint256 gasFee + ) = handleGasAndSwap(zrc20, amount, params.target); + withdraw(params, context.sender, gasFee, gasZRC20, outputAmount, zrc20); } - function swapAndWithdraw( + function swap( address inputToken, uint256 amount, address targetToken, bytes memory recipient, - bool withdraw - ) internal { + bool withdrawFlag + ) public { + IZRC20(inputToken).transferFrom(msg.sender, address(this), amount); + ( + uint256 outputAmount, + address gasZRC20, + uint256 gasFee + ) = handleGasAndSwap(inputToken, amount, targetToken); + withdraw( + Params({ + target: targetToken, + to: recipient, + withdraw: withdrawFlag + }), + msg.sender, + gasFee, + gasZRC20, + outputAmount, + inputToken + ); + } + + function handleGasAndSwap( + address inputToken, + uint256 amount, + address targetToken + ) internal returns (uint256, address, uint256) { uint256 inputForGas; address gasZRC20; uint256 gasFee; - uint256 swapAmount = amount; + uint256 swapAmount; - if (withdraw) { - (gasZRC20, gasFee) = IZRC20(targetToken).withdrawGasFee(); + (gasZRC20, gasFee) = IZRC20(targetToken).withdrawGasFee(); - if (gasZRC20 == inputToken) { - swapAmount = amount - gasFee; - } else { - inputForGas = SwapHelperLib.swapTokensForExactTokens( - uniswapRouter, - inputToken, - gasFee, - gasZRC20, - amount - ); - swapAmount = amount - inputForGas; - } + if (gasZRC20 == inputToken) { + swapAmount = amount - gasFee; + } else { + inputForGas = SwapHelperLib.swapTokensForExactTokens( + uniswapRouter, + inputToken, + gasFee, + gasZRC20, + amount + ); + swapAmount = amount - inputForGas; } uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens( @@ -114,50 +136,73 @@ contract SwapToAnyToken is UniversalContract { targetToken, 0 ); + return (outputAmount, gasZRC20, gasFee); + } - if (withdraw) { - if (gasZRC20 == targetToken) { + function withdraw( + Params memory params, + address sender, + uint256 gasFee, + address gasZRC20, + uint256 outputAmount, + address inputToken + ) public { + if (params.withdraw) { + if (gasZRC20 == params.target) { IZRC20(gasZRC20).approve( address(gateway), outputAmount + gasFee ); } else { IZRC20(gasZRC20).approve(address(gateway), gasFee); - IZRC20(targetToken).approve(address(gateway), outputAmount); + IZRC20(params.target).approve(address(gateway), outputAmount); } gateway.withdraw( - recipient, + abi.encodePacked(params.to), outputAmount, - targetToken, + params.target, RevertOptions({ - revertAddress: address(0), - callOnRevert: false, + revertAddress: address(this), + callOnRevert: true, abortAddress: address(0), - revertMessage: "", + revertMessage: abi.encode(sender, inputToken), onRevertGasLimit: 0 }) ); } else { - IWETH9(targetToken).transfer( - address(uint160(bytes20(recipient))), + IWETH9(params.target).transfer( + address(uint160(bytes20(params.to))), outputAmount ); } } - function swap( - address inputToken, - uint256 amount, - address targetToken, - bytes memory recipient, - bool withdraw - ) public { - IZRC20(inputToken).transferFrom(msg.sender, address(this), amount); + function onRevert(RevertContext calldata context) external onlyGateway { + (address sender, address zrc20) = abi.decode( + context.revertMessage, + (address, address) + ); + (uint256 outputAmount, , ) = handleGasAndSwap( + context.asset, + context.amount, + zrc20 + ); - swapAndWithdraw(inputToken, amount, targetToken, recipient, withdraw); + gateway.withdraw( + abi.encodePacked(sender), + outputAmount, + zrc20, + RevertOptions({ + revertAddress: sender, + callOnRevert: false, + abortAddress: address(0), + revertMessage: "", + onRevertGasLimit: 0 + }) + ); } - function onRevert( - RevertContext calldata revertContext - ) external onlyGateway {} + fallback() external payable {} + + receive() external payable {} } diff --git a/examples/swap/scripts/localnet.sh b/examples/swap/scripts/localnet.sh index 9867ddef..0ea56366 100755 --- a/examples/swap/scripts/localnet.sh +++ b/examples/swap/scripts/localnet.sh @@ -9,19 +9,64 @@ npx hardhat compile --force --quiet ZRC20_ETHEREUM=$(jq -r '.addresses[] | select(.type=="ZRC-20 ETH on 5") | .address' localnet.json) ZRC20_USDC=$(jq -r '.addresses[] | select(.type=="ZRC-20 USDC on 97") | .address' localnet.json) +ZRC20_BNB=$(jq -r '.addresses[] | select(.type=="ZRC-20 BNB on 97") | .address' localnet.json) GATEWAY_ETHEREUM=$(jq -r '.addresses[] | select(.type=="gatewayEVM" and .chain=="ethereum") | .address' localnet.json) GATEWAY_ZETACHAIN=$(jq -r '.addresses[] | select(.type=="gatewayZEVM" and .chain=="zetachain") | .address' localnet.json) UNISWAP_ROUTER=$(jq -r '.addresses[] | select(.type=="uniswapRouterInstance" and .chain=="zetachain") | .address' localnet.json) SENDER=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 -CONTRACT_ZETACHAIN=$(npx hardhat deploy --name Swap --network localhost --gateway "$GATEWAY_ZETACHAIN" --uniswap-router "$UNISWAP_ROUTER" --json | jq -r '.contractAddress') -echo -e "\nšŸš€ Deployed contract on ZetaChain: $CONTRACT_ZETACHAIN" +CONTRACT_SWAP=$(npx hardhat deploy --name Swap --network localhost --gateway "$GATEWAY_ZETACHAIN" --uniswap-router "$UNISWAP_ROUTER" --json | jq -r '.contractAddress') +echo -e "\nšŸš€ Deployed Swap contract on ZetaChain: $CONTRACT_SWAP" + +CONTRACT_SWAPTOANY=$(npx hardhat deploy --name SwapToAnyToken --network localhost --gateway "$GATEWAY_ZETACHAIN" --uniswap-router "$UNISWAP_ROUTER" --json | jq -r '.contractAddress') +echo -e "\nšŸš€ Deployed SwapToAny contract on ZetaChain: $CONTRACT_SWAPTOANY" + +npx hardhat swap-from-evm \ + --network localhost \ + --receiver "$CONTRACT_SWAP" \ + --amount 1 \ + --target "$ZRC20_BNB" \ + --recipient "$SENDER" + +npx hardhat localnet-check + +npx hardhat swap-from-evm \ + --network localhost \ + --receiver "$CONTRACT_SWAP" \ + --amount 1 \ + --target "$ZRC20_BNB" \ + --recipient "$SENDER" \ + --withdraw false + +npx hardhat localnet-check npx hardhat swap-from-evm \ --network localhost \ - --receiver "$CONTRACT_ZETACHAIN" \ + --receiver "$CONTRACT_SWAPTOANY" \ --amount 1 \ - --target "$ZRC20_USDC" \ + --target "$ZRC20_BNB" \ --recipient "$SENDER" +npx hardhat localnet-check + +npx hardhat swap-from-evm \ + --network localhost \ + --receiver "$CONTRACT_SWAPTOANY" \ + --amount 1 \ + --target "$ZRC20_BNB" \ + --recipient "$SENDER" \ + --withdraw false + +npx hardhat localnet-check + +npx hardhat swap-from-zetachain \ + --network localhost \ + --contract "$CONTRACT_SWAPTOANY" \ + --amount 1 \ + --zrc20 "$ZRC20_BNB" \ + --target "$ZRC20_ETHEREUM" \ + --recipient "$SENDER" + +npx hardhat localnet-check + if [ "$1" = "start" ]; then npx hardhat localnet-stop; fi \ No newline at end of file