Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the multioutput example to support Bitcoin #113

Merged
merged 22 commits into from
Apr 4, 2024
Merged

Conversation

lukema95
Copy link
Collaborator

Relevant PR: #101

@fadeev
Copy link
Member

fadeev commented Jan 25, 2024

One final change request is to remove _doSwapAndWithdraw and _doWithdrawal. These functions are not reused within the contract and make it a bit harder to follow the flow. And it saves us about 20 lines of code making the tutorial a bit shorter.

So it would look something like this:

    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();

        (
            address evmRecipient,
            bytes memory btcRecipient,
            address[] memory destinationTokens
        ) = parseMessage(context.chainID, message);

        uint256 totalTransfers = destinationTokens.length;
        if (totalTransfers == 0) revert NoAvailableTransfers();

        uint256 amountToTransfer = amount / totalTransfers;
        uint256 leftOver = amount - amountToTransfer * totalTransfers;

        uint256 lastTransferIndex = destinationTokens[
            destinationTokens.length - 1
        ] == zrc20
            ? destinationTokens.length - 2
            : destinationTokens.length - 1;

        for (uint256 i; i < destinationTokens.length; i++) {
            address targetZRC20 = destinationTokens[i];
            if (targetZRC20 == zrc20) continue;

            if (lastTransferIndex == i) {
                amountToTransfer += leftOver;
            }

            bytes memory recipient = abi.encodePacked(
                BytesHelperLib.addressToBytes(evmRecipient)
            );

            if (targetZRC20 == btcToken) {
                if (btcRecipient.length == 0) revert InvalidRecipient();
                recipient = abi.encodePacked(btcRecipient);
            }
            
            (address gasZRC20, uint256 gasFee) = IZRC20(targetZRC20)
                .withdrawGasFee();

            uint256 outputAmount = SwapHelperLib._doSwap(
                systemContract.wZetaContractAddress(),
                systemContract.uniswapv2FactoryAddress(),
                systemContract.uniswapv2Router02Address(),
                zrc20,
                amountToTransfer,
                targetZRC20,
                0
            );

            if (gasZRC20 != targetZRC20) revert WrongGasContract();
            if (gasFee >= amount) revert NotEnoughToPayGasFee();

            IZRC20(targetZRC20).approve(targetZRC20, gasFee);
            IZRC20(targetZRC20).withdraw(
                abi.encodePacked(recipient),
                amount - gasFee
            );
            emit Withdrawal(targetZRC20, outputAmount, recipient);
        }
    }

@fadeev
Copy link
Member

fadeev commented Jan 25, 2024

Great work, @lukema95! 🎉

@fadeev fadeev marked this pull request as ready for review January 25, 2024 07:18
@lukema95
Copy link
Collaborator Author

One final change request is to remove _doSwapAndWithdraw and _doWithdrawal. These functions are not reused within the contract and make it a bit harder to follow the flow. And it saves us about 20 lines of code making the tutorial a bit shorter.

So it would look something like this:

    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();

        (
            address evmRecipient,
            bytes memory btcRecipient,
            address[] memory destinationTokens
        ) = parseMessage(context.chainID, message);

        uint256 totalTransfers = destinationTokens.length;
        if (totalTransfers == 0) revert NoAvailableTransfers();

        uint256 amountToTransfer = amount / totalTransfers;
        uint256 leftOver = amount - amountToTransfer * totalTransfers;

        uint256 lastTransferIndex = destinationTokens[
            destinationTokens.length - 1
        ] == zrc20
            ? destinationTokens.length - 2
            : destinationTokens.length - 1;

        for (uint256 i; i < destinationTokens.length; i++) {
            address targetZRC20 = destinationTokens[i];
            if (targetZRC20 == zrc20) continue;

            if (lastTransferIndex == i) {
                amountToTransfer += leftOver;
            }

            bytes memory recipient = abi.encodePacked(
                BytesHelperLib.addressToBytes(evmRecipient)
            );

            if (targetZRC20 == btcToken) {
                if (btcRecipient.length == 0) revert InvalidRecipient();
                recipient = abi.encodePacked(btcRecipient);
            }
            
            (address gasZRC20, uint256 gasFee) = IZRC20(targetZRC20)
                .withdrawGasFee();

            uint256 outputAmount = SwapHelperLib._doSwap(
                systemContract.wZetaContractAddress(),
                systemContract.uniswapv2FactoryAddress(),
                systemContract.uniswapv2Router02Address(),
                zrc20,
                amountToTransfer,
                targetZRC20,
                0
            );

            if (gasZRC20 != targetZRC20) revert WrongGasContract();
            if (gasFee >= amount) revert NotEnoughToPayGasFee();

            IZRC20(targetZRC20).approve(targetZRC20, gasFee);
            IZRC20(targetZRC20).withdraw(
                abi.encodePacked(recipient),
                amount - gasFee
            );
            emit Withdrawal(targetZRC20, outputAmount, recipient);
        }
    }

Hi @fadeev , I've extracted the _doSwapAndWithdraw and _doWithdrawal functions because the above will cause a deep stack error at compile time, looks like below:

npx hardhat compile --force
CompilerError: Stack too deep, try removing local variables.
   --> contracts/MultiOutput.sol:147:17:
    |
147 |                 zrc20,
    |                 ^^^^^

The error is the following function:

            uint256 outputAmount = SwapHelperLib._doSwap(
                systemContract.wZetaContractAddress(),
                systemContract.uniswapv2FactoryAddress(),
                systemContract.uniswapv2Router02Address(),
                zrc20,
                amountToTransfer,
                targetZRC20,
                0
            );

@fadeev
Copy link
Member

fadeev commented Jan 25, 2024

@andresaiello please, review.

@fadeev
Copy link
Member

fadeev commented Jan 25, 2024

@lukema95 ok, cool. Can you please resolve the yarn conflict, and we should be good to go 👍

@fadeev
Copy link
Member

fadeev commented Jan 25, 2024

btw this PR doesn't add support for ERC-20s, so we might want to change the title.

Copy link

socket-security bot commented Jan 25, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@nomicfoundation/[email protected] filesystem, shell Transitive: environment +7 110 kB fvictorio
npm/@zetachain/[email protected] Transitive: environment, filesystem, network, shell +119 94.1 MB lucasjanon
npm/[email protected] environment, filesystem, network, shell Transitive: eval +165 40.2 MB fvictorio

🚮 Removed packages: npm/@eslint-community/[email protected], npm/@zetachain/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected]

View full report↗︎

@lukema95
Copy link
Collaborator Author

btw this PR doesn't add support for ERC-20s, so we might want to change the title.

Change to “Update the multioutput example to support Bitcoin ?”

@lukema95 lukema95 changed the title Update the multioutput example to support Bitcoin and ERC-20s Update the multioutput example to support Bitcoin Jan 26, 2024
@fadeev
Copy link
Member

fadeev commented Mar 11, 2024

Removed the _doWithdrawal function, because it wasn't used anywhere in the code.

@fadeev
Copy link
Member

fadeev commented Mar 11, 2024

Removed bytesMemoryToAddress, because it comes out of the box in the upcoming version of the toolkit, so we can import it instead like so: BytesHelperLib.bytesMemoryToAddress (the implementation of the function is the same).

@fadeev
Copy link
Member

fadeev commented Mar 13, 2024

@lukema95 I'm having issues with the contract, can't get it to work.

npx hardhat interact --contract 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 --network mumbai_testnet  --target-token 0xd97B1de3619ed2c6BEb3860147E30cA8A7dC9891,0x13A0c5930C028511Dc02665E7285134B6d11A5f4 --amount 5 --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 --btc-recipient tb1q8shzf7afc3rhw8n6w6ec32s8h6e2mrw077d0gg 
🔑 Using account: 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32

🚀 Successfully broadcasted a token transfer transaction on mumbai_testnet network.
📝 Transaction hash: 0x71a4a8acfa93fde13815fbcdddbb92991d75355c52771078b3f1a198b799575b

~/template npx hardhat cctx 0x71a4a8acfa93fde13815fbcdddbb92991d75355c52771078b3f1a198b799575b
^CCCTXs on ZetaChain found.

⠦ 0x99356aa7b2e8de671e7e25a8e24246149ae0d0b70c43734d62a45da69edf2f09: 80001 → 7001: PendingRevert
 (contract call failed: method 'depositAndCall', contract '0xEdf1c3275d13489aCdC6cD6eD246E72458B8
795B', args: [{[73 85 163 243 143 248 106 233 42 145 68 69 9 156 170 142 162 185 186 50] 0x000000
0000000000000000000000000000000000 80001} 0x48f80608B672DC30DC7e3dbBd0343c5F02C738Eb 500000000000
0000000 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 [0 0 0 0 0 0 0 0 0 0 0 0 73 85 163 243 143 248
 106 233 42 145 68 69 9 156 170 142 162 185 186 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 192 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 116 98 49 113 56 115 104 122 102 55 97 102 9
9 51 114 104 119 56 110 54 119 54 101 99 51 50 115 56 104 54 101 50 109 114 119 48 55 55 100 48 1
03 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 0 0 0 0 0 217 123 29 227 97 158 210 198 190 179 134 1 71 227 12 
168 167 220 152 145 0 0 0 0 0 0 0 0 0 0 0 0 19 160 197 147 12 2 133 17 220 2 102 94 114 133 19 75
 109 17 165 244]]: execution reverted: ret 0x: evm transaction execution failed)
npx hardhat interact --contract 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 --network mumbai_testnet  --target-token 0xd97B1de3619ed2c6BEb3860147E30cA8A7dC9891,0x13A0c5930C028511Dc02665E7285134B6d11A5f4 --amount 50 --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 --btc-recipient tb1q8shzf7afc3rhw8n6w6ec32s8h6e2mrw077d0gg
🔑 Using account: 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32

🚀 Successfully broadcasted a token transfer transaction on mumbai_testnet network.
📝 Transaction hash: 0x9cbc03bacf6b588fd72175bb8008c417df369355eb259f8894bd1753d20a78a9

~/template npx hardhat cctx 0x9cbc03bacf6b588fd72175bb8008c417df369355eb259f8894bd1753d20a78a9
✓ CCTXs on ZetaChain found.

⠴ 0xfcc7266f59af433cf612e072e4a579c9f4a29ee805452ae97c97effe006e8d2e: 80001 → 7001: PendingRevert
 (contract call failed: method 'depositAndCall', contract '0xEdf1c3275d13489aCdC6cD6eD246E72458B8
795B', args: [{[73 85 163 243 143 248 106 233 42 145 68 69 9 156 170 142 162 185 186 50] 0x000000
0000000000000000000000000000000000 80001} 0x48f80608B672DC30DC7e3dbBd0343c5F02C738Eb 500000000000
00000000 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 [0 0 0 0 0 0 0 0 0 0 0 0 73 85 163 243 143 24
8 106 233 42 145 68 69 9 156 170 142 162 185 186 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0^C0 0 0 0 0 0 0 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 192 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 116 98 49 113 56 115 104 122 102 55 97 102 
99 51 114 104 119 56 110 54 119 54 101 99 51 50 115 56 104 54 101 50 109 114 119 48 55 55 100 48 
103 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 0 0 0 0 0 217 123 29 227 97 158 210 198 190 179 134 1 71 227 12
 168 167 220 152 145 0 0 0 0 0 0 0 0 0 0 0 0 19 160 197 147 12 2 133 17 220 2 102 94 114 133 19 7
5 109 17 165 244]]: execution reverted: ret 0x: evm transaction execution failed)
npx hardhat interact --contract 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 --network bsc_testnet  --target-token 0x48f80608B672DC30DC7e3dbBd0343c5F02C738Eb,0x13A0c5930C028511Dc02665E7285134B6d11A5f4 --amount 2 --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32                 
🔑 Using account: 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32

🚀 Successfully broadcasted a token transfer transaction on bsc_testnet network.
📝 Transaction hash: 0x135b014f63fead4c3e6841e22e30aed2c258ad25e6c1d16ee140ea5f507c04ff

~/template npx hardhat cctx 0x135b014f63fead4c3e6841e22e30aed2c258ad25e6c1d16ee140ea5f507c04ff
^CCCTXs on ZetaChain found.

⠏ 0x6131f7991982f89400f2ae5bfbfc41439d68856ed4b658d9b01df7ef57625e92: 97 → 7001: PendingRevert (c
ontract call failed: method 'depositAndCall', contract '0xEdf1c3275d13489aCdC6cD6eD246E72458B8795
B', args: [{[73 85 163 243 143 248 106 233 42 145 68 69 9 156 170 142 162 185 186 50] 0x000000000
0000000000000000000000000000000 97} 0xd97B1de3619ed2c6BEb3860147E30cA8A7dC9891 200000000000000000
0 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 [0 0 0 0 0 0 0 0 0 0 0 0 73 85 163 243 143 248 106 2
33 42 145 68 69 9 156 170 142 162 185 186 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 64 0 0 0 0 0 0 0 0 0 0 0 0 72 248 6 8 182 114 220 48 220 126 61 187 208 52 60 95 2 199
 56 235 0 0 0 0 0 0 0 0 0 0 0 0 19 160 197 147 12 2 133 17 220 2 102 94 114 133 19 75 109 17 165 
244]]: execution reverted: ret 0x: evm transaction execution failed)
npx hardhat interact --contract 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 --network bsc_testnet  --target-token 0x48f80608B672DC30DC7e3dbBd0343c5F02C738Eb --amount 2 --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32                                          
🔑 Using account: 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32

🚀 Successfully broadcasted a token transfer transaction on bsc_testnet network.
📝 Transaction hash: 0xb8f604f5c2c20c6180ef2f52b5ce6f9656f94bdd04842d7bf04546ffa3d39668

~/template npx hardhat cctx 0xb8f604f5c2c20c6180ef2f52b5ce6f9656f94bdd04842d7bf04546ffa3d39668
^CCCTXs on ZetaChain found.

⠋ 0xfa82f24252f08aa626ace1dda67d6331d37771291a1000f8f4f2081f66d55ce0: 97 → 7001: PendingRevert (c
ontract call failed: method 'depositAndCall', contract '0xEdf1c3275d13489aCdC6cD6eD246E72458B8795
B', args: [{[73 85 163 243 143 248 106 233 42 145 68 69 9 156 170 142 162 185 186 50] 0x000000000
0000000000000000000000000000000 97} 0xd97B1de3619ed2c6BEb3860147E30cA8A7dC9891 200000000000000000
0 0x2369A46C1EF38772e24cA2B3722E75d78bb7b322 [0 0 0 0 0 0 0 0 0 0 0 0 73 85 163 243 143 248 106 2
33 42 145 68 69 9 156 170 142 162 185 186 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 72 248 6 8 182 114 220 48 220 126 61 187 208 52 60 95 2 199
 56 235]]: execution reverted: ret 0x: evm transaction execution failed)

Copy link
Member

@fadeev fadeev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npx hardhat interact --contract 0xa573Df1F0729FE6F1BD69b0a5dbFE393e6e09f47 --network mumbai_testnet  --target-token 0xd97B1de3619ed2c6BEb3860147E30cA8A7dC9891,0x65a45c57636f9BcCeD4fe193A602008578BcA90b --amount 50 --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 --btc-recipient tb1q8shzf7afc3rhw8n6w6ec32s8h6e2mrw077d0gg
npx hardhat cctx 0x642446f8b3d20d12f58cbbf2de33377e3c92d016f043deb81c5b854e7a440cd0
✓ CCTXs on ZetaChain found.

✓ 0x7b54665297fb6779da417ca431dd764b15f2237e3d7efbc0881e3801cced4fce: 80001 → 7001: OutboundMined (Remote omnicha
in contract call completed)
✓ 0xbd97de12a390e767491d5d6cbeed30a08b9c69adac7becee0be8cbb46ced93d2: 7001 → 97: OutboundMined 
⠋ 0x468e11ea759a3683ec89467ee2c47dde3f8245c984c41886c7a3712e5956e349: 7001 → 18332: PendingOutbound 

@fadeev fadeev merged commit ac4d2c7 into main Apr 4, 2024
5 checks passed
@fadeev fadeev deleted the multi-output branch April 4, 2024 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants