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

Swap: add Solana interact task #192

Merged
merged 3 commits into from
Aug 30, 2024
Merged

Swap: add Solana interact task #192

merged 3 commits into from
Aug 30, 2024

Conversation

fadeev
Copy link
Member

@fadeev fadeev commented Aug 29, 2024

npx hardhat interact-solana --amount 0.1 --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 --target-token 0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0 --withdraw true --contract 0x928363107ebA799D91d0184c53b58cBf15eE7A78
Deposit transaction signature: 4415FPh1cceJ1NtBAuFEWnnp9pV8YhN1EQVvydG83KVhfhSzB8WWX1Qi4HF84yvwAcCqVsNu1rAAHCN43GdAbbYX

Solana -> ZetaChain:

https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/crosschain/inTxHashToCctxData/4415FPh1cceJ1NtBAuFEWnnp9pV8YhN1EQVvydG83KVhfhSzB8WWX1Qi4HF84yvwAcCqVsNu1rAAHCN43GdAbbYX

ZetaChain -> Ethereum Sepolia:

https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/crosschain/cctx/0xd8e59d0b3ea1b34dc6b0b5ae3563864f59a0a969aea2e60be95e977c1f04cfe0

Summary by CodeRabbit

  • New Features

    • Introduced a new deposit function for Solana blockchain interactions.
    • Added a Hardhat task for interacting with Solana contracts.
    • Created a configuration file for the Foundry framework to enhance build processes.
  • Improvements

    • Streamlined the README for a more focused user guide.
    • Enhanced parameter handling in smart contract functions for better readability.
  • Bug Fixes

    • Removed unnecessary error declarations and functions in contracts for improved clarity.
  • Chores

    • Updated dependencies and scripts in the package configuration to support new functionalities.

Copy link

coderabbitai bot commented Aug 29, 2024

Walkthrough

Walkthrough

The changes across the omnichain/swap directory include updates to configuration files, contract modifications, and the introduction of new scripts and tasks. Notable alterations involve the restructuring of smart contract parameters, the addition of a foundry.toml file for Foundry configuration, and the introduction of new tasks for interacting with the Solana blockchain. The README.md has been streamlined to focus on essential information, while the .gitignore file has been updated to exclude specific build artifacts.

Changes

File Path Change Summary
omnichain/swap/.gitignore Added entries to exclude dependencies, out, and cache_forge directories.
omnichain/swap/README.md Condensed content to focus on installation and tutorials, removing detailed Hardhat task explanations.
omnichain/swap/contracts/Swap.sol Modified swapAndWithdraw function to use params.target and params.to. Changed input token reference from inputToken to zrc20.
omnichain/swap/contracts/SwapToAnyToken.sol Removed TransferFailed error and receive() function. Refactored onCrossChainCall and swapAndWithdraw to use params structure for improved readability.
omnichain/swap/contracts/shared/TestUniswapCore.sol Added newline at the end of the file for formatting.
omnichain/swap/contracts/shared/TestUniswapRouter.sol Added newline at the end of the file for formatting.
omnichain/swap/foundry.toml Introduced configuration file defining profiles and dependencies for the Foundry framework.
omnichain/swap/hardhat.config.ts Added imports for interact task and @zetachain/localnet/tasks. Removed optimizer settings.
omnichain/swap/package.json Added new "deploy" script. Updated dependencies and replaced @zetachain/toolkit with @zetachain/localnet.
omnichain/swap/tasks/interact.ts Reorganized import statements for clarity.
omnichain/swap/tasks/solana/deposit.ts Introduced a new function for depositing tokens on the Solana blockchain.
omnichain/swap/tasks/solana/gateway.json Introduced a JSON file defining a Solana-based gateway structure with instructions for deposits and withdrawals.
omnichain/swap/tasks/solana/interact.ts Introduced a Hardhat task for interacting with Solana contracts for depositing SOL tokens.
omnichain/swap/test/SwapToAnyToken.spec.ts Adjusted formatting for readability in the deployment of swapToAnyToken instance.
omnichain/swap/tsconfig.json Changed module option from "commonjs" to "nodenext" and added moduleResolution option.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between dfbf923 and 5f9a0dd.

Files ignored due to path filters (2)
  • omnichain/swap/package-lock.json is excluded by !**/package-lock.json
  • omnichain/swap/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
Files selected for processing (15)
  • omnichain/swap/.gitignore (1 hunks)
  • omnichain/swap/README.md (1 hunks)
  • omnichain/swap/contracts/Swap.sol (1 hunks)
  • omnichain/swap/contracts/SwapToAnyToken.sol (4 hunks)
  • omnichain/swap/contracts/shared/TestUniswapCore.sol (1 hunks)
  • omnichain/swap/contracts/shared/TestUniswapRouter.sol (1 hunks)
  • omnichain/swap/foundry.toml (1 hunks)
  • omnichain/swap/hardhat.config.ts (2 hunks)
  • omnichain/swap/package.json (4 hunks)
  • omnichain/swap/tasks/interact.ts (1 hunks)
  • omnichain/swap/tasks/solana/deposit.ts (1 hunks)
  • omnichain/swap/tasks/solana/gateway.json (1 hunks)
  • omnichain/swap/tasks/solana/interact.ts (1 hunks)
  • omnichain/swap/test/SwapToAnyToken.spec.ts (1 hunks)
  • omnichain/swap/tsconfig.json (1 hunks)
Files skipped from review due to trivial changes (6)
  • omnichain/swap/.gitignore
  • omnichain/swap/contracts/shared/TestUniswapCore.sol
  • omnichain/swap/contracts/shared/TestUniswapRouter.sol
  • omnichain/swap/foundry.toml
  • omnichain/swap/tasks/interact.ts
  • omnichain/swap/test/SwapToAnyToken.spec.ts
Additional context used
Markdownlint
omnichain/swap/README.md

7-7: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

Additional comments not posted (22)
omnichain/swap/tsconfig.json (2)

3-3: LGTM!

Changing the module option to "nodenext" aligns the project with the latest Node.js module handling practices, allowing for better interoperability with ES modules.


4-4: LGTM!

Adding the moduleResolution option with the value "nodenext" ensures consistent module resolution in line with the latest Node.js practices.

omnichain/swap/README.md (2)

5-7: LGTM!

The addition of installation instructions is clear and concise, providing essential information for getting started.

Tools
Markdownlint

7-7: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


13-15: LGTM!

The new section effectively guides users to further learning resources, enhancing the onboarding experience.

omnichain/swap/hardhat.config.ts (2)

2-2: LGTM!

The addition of the import for Solana interaction expands the project's functionality to support interactions with the Solana blockchain.


3-3: LGTM!

The addition of the import for local network tasks enhances the project's capabilities by supporting local network tasks.

omnichain/swap/tasks/solana/interact.ts (1)

1-6: LGTM!

The import statements are necessary and correctly included.

omnichain/swap/tasks/solana/deposit.ts (1)

1-6: LGTM!

The import statements are necessary and correctly included.

omnichain/swap/package.json (6)

9-9: LGTM!

The addition of the "lint" script is a good practice to ensure code quality.


10-10: LGTM!

The addition of the "deploy" script enhances the project's deployment capabilities.


19-19: LGTM!

The addition of the @nomicfoundation/hardhat-foundry dependency indicates an integration with the Foundry framework, which can be beneficial for the project.


31-31: LGTM!

The replacement of the @zetachain/toolkit dependency with @zetachain/localnet suggests a shift in the toolkit being utilized for ZetaChain-related functionalities.


32-32: LGTM!

The addition of the @zetachain/protocol-contracts dependency indicates the use of protocol contracts for ZetaChain-related functionalities.


47-47: LGTM!

The update of the hardhat dependency version may include important bug fixes or new features relevant to the development environment.

omnichain/swap/contracts/SwapToAnyToken.sol (7)

Line range hint 1-1: LGTM!

The removal of the TransferFailed error declaration simplifies error handling within the contract.


Line range hint 1-1: LGTM!

The removal of the receive() function indicates a shift in the contract's handling of incoming funds.


40-48: LGTM!

The refactoring of the onCrossChainCall function consolidates the handling of the params structure and simplifies the decoding of the message variable.


Line range hint 58-80: LGTM!

The update to the swapAndWithdraw function reduces the function signature's complexity and enhances the maintainability of the code.


Line range hint 1-1: LGTM!

The removal of the swap function indicates a potential shift in how the contract handles token swaps.


78-82: LGTM!

The update to the withdrawal process streamlines the code and ensures consistency in how withdrawal actions are processed.


Line range hint 1-1: LGTM!

The removal of checks for the wZetaContractAddress and associated Ether withdrawal logic indicates a potential shift in how the contract interacts with wrapped tokens.

omnichain/swap/tasks/solana/gateway.json (1)

1-497: LGTM! But verify the consistency of the definitions with the program's logic.

The file appears to be well-structured and follows the conventions for Solana programs. However, ensure that the instructions, accounts, and errors are correctly defined and consistent with the program's logic.

Comment on lines +28 to +35
task("interact-solana", "", main)
.addParam("amount", "Amount of SOL to deposit")
.addParam("contract", "Universal contract address")
.addParam("targetToken")
.addParam("recipient")
.addOptionalParam("withdraw")
.addOptionalParam("api", "Solana API", "https://api.devnet.solana.com")
.addOptionalParam("idPath", "Path to id.json", "~/.config/solana/id.json");
Copy link

Choose a reason for hiding this comment

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

Enhance parameter validation.

The task registration is correctly implemented but could benefit from additional parameter validation.

Add validation for the recipient parameter.

Apply this diff to enhance the task registration:

task("interact-solana", "", main)
  .addParam("amount", "Amount of SOL to deposit")
  .addParam("contract", "Universal contract address")
  .addParam("targetToken")
  .addParam("recipient", "Recipient address")
  .addOptionalParam("withdraw")
  .addOptionalParam("api", "Solana API", "https://api.devnet.solana.com")
  .addOptionalParam("idPath", "Path to id.json", "~/.config/solana/id.json")
  .addAction(async (args, hre) => {
    if (!args.recipient || args.recipient.length === 0) {
      throw new Error("Invalid recipient address");
    }
  });
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
task("interact-solana", "", main)
.addParam("amount", "Amount of SOL to deposit")
.addParam("contract", "Universal contract address")
.addParam("targetToken")
.addParam("recipient")
.addOptionalParam("withdraw")
.addOptionalParam("api", "Solana API", "https://api.devnet.solana.com")
.addOptionalParam("idPath", "Path to id.json", "~/.config/solana/id.json");
task("interact-solana", "", main)
.addParam("amount", "Amount of SOL to deposit")
.addParam("contract", "Universal contract address")
.addParam("targetToken")
.addParam("recipient", "Recipient address")
.addOptionalParam("withdraw")
.addOptionalParam("api", "Solana API", "https://api.devnet.solana.com")
.addOptionalParam("idPath", "Path to id.json", "~/.config/solana/id.json")
.addAction(async (args, hre) => {
if (!args.recipient || args.recipient.length === 0) {
throw new Error("Invalid recipient address");
}
});

Comment on lines +8 to +26
const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
let recipient;
try {
if (bech32.decode(args.recipient)) {
recipient = utils.solidityPack(
["bytes"],
[utils.toUtf8Bytes(args.recipient)]
);
}
} catch (e) {
recipient = args.recipient;
}
const { amount, contract, targetToken, withdraw, api, idPath } = args;
const params = [
["address", "bytes", "bool"],
[targetToken, recipient, withdraw],
];
await deposit({ amount, api, contract, idPath, params });
};
Copy link

Choose a reason for hiding this comment

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

Enhance input validation and error handling.

The main function is correctly implemented but could benefit from additional input validation and error handling.

  • Add input validation for amount, contract, and targetToken.
  • Improve error handling for the bech32.decode call.

Apply this diff to enhance the function:

const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
  let recipient;

  // Validate inputs
  if (!args.amount || isNaN(args.amount) || args.amount <= 0) {
    throw new Error("Invalid amount");
  }
  if (!args.contract || !utils.isAddress(args.contract)) {
    throw new Error("Invalid contract address");
  }
  if (!args.targetToken || !utils.isAddress(args.targetToken)) {
    throw new Error("Invalid target token address");
  }

  try {
    if (bech32.decode(args.recipient)) {
      recipient = utils.solidityPack(
        ["bytes"],
        [utils.toUtf8Bytes(args.recipient)]
      );
    }
  } catch (e) {
    recipient = args.recipient;
  }

  const { amount, contract, targetToken, withdraw, api, idPath } = args;
  const params = [
    ["address", "bytes", "bool"],
    [targetToken, recipient, withdraw],
  ];
  await deposit({ amount, api, contract, idPath, params });
};
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
let recipient;
try {
if (bech32.decode(args.recipient)) {
recipient = utils.solidityPack(
["bytes"],
[utils.toUtf8Bytes(args.recipient)]
);
}
} catch (e) {
recipient = args.recipient;
}
const { amount, contract, targetToken, withdraw, api, idPath } = args;
const params = [
["address", "bytes", "bool"],
[targetToken, recipient, withdraw],
];
await deposit({ amount, api, contract, idPath, params });
};
const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
let recipient;
// Validate inputs
if (!args.amount || isNaN(args.amount) || args.amount <= 0) {
throw new Error("Invalid amount");
}
if (!args.contract || !utils.isAddress(args.contract)) {
throw new Error("Invalid contract address");
}
if (!args.targetToken || !utils.isAddress(args.targetToken)) {
throw new Error("Invalid target token address");
}
try {
if (bech32.decode(args.recipient)) {
recipient = utils.solidityPack(
["bytes"],
[utils.toUtf8Bytes(args.recipient)]
);
}
} catch (e) {
recipient = args.recipient;
}
const { amount, contract, targetToken, withdraw, api, idPath } = args;
const params = [
["address", "bytes", "bool"],
[targetToken, recipient, withdraw],
];
await deposit({ amount, api, contract, idPath, params });
};

Comment on lines +10 to +65
export const deposit = async (args: {
amount: number;
api: string;
contract: string;
idPath: string;
params: any[];
}) => {
const keypair = await getKeypairFromFile(args.idPath);
const wallet = new anchor.Wallet(keypair);

const connection = new anchor.web3.Connection(args.api);
const provider = new anchor.AnchorProvider(
connection,
wallet,
anchor.AnchorProvider.defaultOptions()
);
anchor.setProvider(provider);

const programId = new web3.PublicKey(Gateway_IDL.address);
const gatewayProgram = new Program(Gateway_IDL as anchor.Idl, provider);

const seeds = [Buffer.from(SEED, "utf-8")];
const [pdaAccount] = web3.PublicKey.findProgramAddressSync(seeds, programId);

const depositAmount = new BN(web3.LAMPORTS_PER_SOL * args.amount);

try {
const tx = new web3.Transaction();
const m = Buffer.from(
ethers.utils.arrayify(
args.contract +
ethers.utils.defaultAbiCoder
.encode(args.params[0], args.params[1])
.slice(2)
)
);
const depositInstruction = await gatewayProgram.methods
.deposit(depositAmount, m)
.accounts({
pda: pdaAccount,
signer: wallet.publicKey,
systemProgram: web3.SystemProgram.programId,
})
.instruction();

tx.add(depositInstruction);

// Send the transaction
const txSignature = await web3.sendAndConfirmTransaction(connection, tx, [
keypair,
]);

console.log("Transaction signature:", txSignature);
} catch (error) {
console.error("Transaction failed:", error);
}
Copy link

Choose a reason for hiding this comment

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

Enhance input validation and error handling.

The deposit function is correctly implemented but could benefit from additional input validation and error handling.

  • Add input validation for amount, contract, and api.
  • Improve error handling for the transaction execution.

Apply this diff to enhance the function:

export const deposit = async (args: {
  amount: number;
  api: string;
  contract: string;
  idPath: string;
  params: any[];
}) => {
  // Validate inputs
  if (!args.amount || isNaN(args.amount) || args.amount <= 0) {
    throw new Error("Invalid amount");
  }
  if (!args.contract || !ethers.utils.isAddress(args.contract)) {
    throw new Error("Invalid contract address");
  }
  if (!args.api || !args.api.startsWith("http")) {
    throw new Error("Invalid API URL");
  }

  const keypair = await getKeypairFromFile(args.idPath);
  const wallet = new anchor.Wallet(keypair);

  const connection = new anchor.web3.Connection(args.api);
  const provider = new anchor.AnchorProvider(
    connection,
    wallet,
    anchor.AnchorProvider.defaultOptions()
  );
  anchor.setProvider(provider);

  const programId = new web3.PublicKey(Gateway_IDL.address);
  const gatewayProgram = new Program(Gateway_IDL as anchor.Idl, provider);

  const seeds = [Buffer.from(SEED, "utf-8")];
  const [pdaAccount] = web3.PublicKey.findProgramAddressSync(seeds, programId);

  const depositAmount = new BN(web3.LAMPORTS_PER_SOL * args.amount);

  try {
    const tx = new web3.Transaction();
    const m = Buffer.from(
      ethers.utils.arrayify(
        args.contract +
          ethers.utils.defaultAbiCoder
            .encode(args.params[0], args.params[1])
            .slice(2)
      )
    );
    const depositInstruction = await gatewayProgram.methods
      .deposit(depositAmount, m)
      .accounts({
        pda: pdaAccount,
        signer: wallet.publicKey,
        systemProgram: web3.SystemProgram.programId,
      })
      .instruction();

    tx.add(depositInstruction);

    // Send the transaction
    const txSignature = await web3.sendAndConfirmTransaction(connection, tx, [
      keypair,
    ]);

    console.log("Transaction signature:", txSignature);
  } catch (error) {
    console.error("Transaction failed:", error);
  }
};
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const deposit = async (args: {
amount: number;
api: string;
contract: string;
idPath: string;
params: any[];
}) => {
const keypair = await getKeypairFromFile(args.idPath);
const wallet = new anchor.Wallet(keypair);
const connection = new anchor.web3.Connection(args.api);
const provider = new anchor.AnchorProvider(
connection,
wallet,
anchor.AnchorProvider.defaultOptions()
);
anchor.setProvider(provider);
const programId = new web3.PublicKey(Gateway_IDL.address);
const gatewayProgram = new Program(Gateway_IDL as anchor.Idl, provider);
const seeds = [Buffer.from(SEED, "utf-8")];
const [pdaAccount] = web3.PublicKey.findProgramAddressSync(seeds, programId);
const depositAmount = new BN(web3.LAMPORTS_PER_SOL * args.amount);
try {
const tx = new web3.Transaction();
const m = Buffer.from(
ethers.utils.arrayify(
args.contract +
ethers.utils.defaultAbiCoder
.encode(args.params[0], args.params[1])
.slice(2)
)
);
const depositInstruction = await gatewayProgram.methods
.deposit(depositAmount, m)
.accounts({
pda: pdaAccount,
signer: wallet.publicKey,
systemProgram: web3.SystemProgram.programId,
})
.instruction();
tx.add(depositInstruction);
// Send the transaction
const txSignature = await web3.sendAndConfirmTransaction(connection, tx, [
keypair,
]);
console.log("Transaction signature:", txSignature);
} catch (error) {
console.error("Transaction failed:", error);
}
export const deposit = async (args: {
amount: number;
api: string;
contract: string;
idPath: string;
params: any[];
}) => {
// Validate inputs
if (!args.amount || isNaN(args.amount) || args.amount <= 0) {
throw new Error("Invalid amount");
}
if (!args.contract || !ethers.utils.isAddress(args.contract)) {
throw new Error("Invalid contract address");
}
if (!args.api || !args.api.startsWith("http")) {
throw new Error("Invalid API URL");
}
const keypair = await getKeypairFromFile(args.idPath);
const wallet = new anchor.Wallet(keypair);
const connection = new anchor.web3.Connection(args.api);
const provider = new anchor.AnchorProvider(
connection,
wallet,
anchor.AnchorProvider.defaultOptions()
);
anchor.setProvider(provider);
const programId = new web3.PublicKey(Gateway_IDL.address);
const gatewayProgram = new Program(Gateway_IDL as anchor.Idl, provider);
const seeds = [Buffer.from(SEED, "utf-8")];
const [pdaAccount] = web3.PublicKey.findProgramAddressSync(seeds, programId);
const depositAmount = new BN(web3.LAMPORTS_PER_SOL * args.amount);
try {
const tx = new web3.Transaction();
const m = Buffer.from(
ethers.utils.arrayify(
args.contract +
ethers.utils.defaultAbiCoder
.encode(args.params[0], args.params[1])
.slice(2)
)
);
const depositInstruction = await gatewayProgram.methods
.deposit(depositAmount, m)
.accounts({
pda: pdaAccount,
signer: wallet.publicKey,
systemProgram: web3.SystemProgram.programId,
})
.instruction();
tx.add(depositInstruction);
// Send the transaction
const txSignature = await web3.sendAndConfirmTransaction(connection, tx, [
keypair,
]);
console.log("Transaction signature:", txSignature);
} catch (error) {
console.error("Transaction failed:", error);
}
};

Comment on lines +49 to +68
(gasZRC20, gasFee) = IZRC20(params.target).withdrawGasFee();

inputForGas = SwapHelperLib.swapTokensForExactTokens(
systemContract,
inputToken,
zrc20,
gasFee,
gasZRC20,
amount
);

uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens(
systemContract,
inputToken,
zrc20,
amount - inputForGas,
targetToken,
params.target,
0
);

IZRC20(gasZRC20).approve(targetToken, gasFee);
IZRC20(targetToken).withdraw(recipient, outputAmount);
IZRC20(gasZRC20).approve(params.target, gasFee);
IZRC20(params.target).withdraw(params.to, outputAmount);
Copy link

Choose a reason for hiding this comment

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

Add comments explaining the new params structure.

The changes improve the clarity and consistency of the function but could benefit from additional comments explaining the new params structure.

Add comments to explain the new params structure.

Apply this diff to enhance the function:

function onCrossChainCall(
    zContext calldata context,
    address zrc20,
    uint256 amount,
    bytes calldata message
) external virtual override onlySystem(systemContract) {
    Params memory params = Params({target: address(0), to: bytes("")});

    if (context.chainID == BITCOIN) {
        params.target = BytesHelperLib.bytesToAddress(message, 0);
        params.to = abi.encodePacked(
            BytesHelperLib.bytesToAddress(message, 20)
        );
    } else {
        (address targetToken, bytes memory recipient) = abi.decode(
            message,
            (address, bytes)
        );
        params.target = targetToken;
        params.to = recipient;
    }

    uint256 inputForGas;
    address gasZRC20;
    uint256 gasFee;

    // Retrieve the gas fee for the target token
    (gasZRC20, gasFee) = IZRC20(params.target).withdrawGasFee();

    // Swap tokens for the exact amount of gas fee
    inputForGas = SwapHelperLib.swapTokensForExactTokens(
        systemContract,
        zrc20,
        gasFee,
        gasZRC20,
        amount
    );

    // Swap the remaining tokens for the target token
    uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens(
        systemContract,
        zrc20,
        amount - inputForGas,
        params.target,
        0
    );

    // Approve the target token for withdrawal
    IZRC20(gasZRC20).approve(params.target, gasFee);
    // Withdraw the target token to the recipient
    IZRC20(params.target).withdraw(params.to, outputAmount);
}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(gasZRC20, gasFee) = IZRC20(params.target).withdrawGasFee();
inputForGas = SwapHelperLib.swapTokensForExactTokens(
systemContract,
inputToken,
zrc20,
gasFee,
gasZRC20,
amount
);
uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens(
systemContract,
inputToken,
zrc20,
amount - inputForGas,
targetToken,
params.target,
0
);
IZRC20(gasZRC20).approve(targetToken, gasFee);
IZRC20(targetToken).withdraw(recipient, outputAmount);
IZRC20(gasZRC20).approve(params.target, gasFee);
IZRC20(params.target).withdraw(params.to, outputAmount);
function onCrossChainCall(
zContext calldata context,
address zrc20,
uint256 amount,
bytes calldata message
) external virtual override onlySystem(systemContract) {
Params memory params = Params({target: address(0), to: bytes("")});
if (context.chainID == BITCOIN) {
params.target = BytesHelperLib.bytesToAddress(message, 0);
params.to = abi.encodePacked(
BytesHelperLib.bytesToAddress(message, 20)
);
} else {
(address targetToken, bytes memory recipient) = abi.decode(
message,
(address, bytes)
);
params.target = targetToken;
params.to = recipient;
}
uint256 inputForGas;
address gasZRC20;
uint256 gasFee;
// Retrieve the gas fee for the target token
(gasZRC20, gasFee) = IZRC20(params.target).withdrawGasFee();
// Swap tokens for the exact amount of gas fee
inputForGas = SwapHelperLib.swapTokensForExactTokens(
systemContract,
zrc20,
gasFee,
gasZRC20,
amount
);
// Swap the remaining tokens for the target token
uint256 outputAmount = SwapHelperLib.swapExactTokensForTokens(
systemContract,
zrc20,
amount - inputForGas,
params.target,
0
);
// Approve the target token for withdrawal
IZRC20(gasZRC20).approve(params.target, gasFee);
// Withdraw the target token to the recipient
IZRC20(params.target).withdraw(params.to, outputAmount);
}

@fadeev fadeev merged commit d240d32 into main Aug 30, 2024
12 checks passed
@fadeev fadeev deleted the swap-interact-solana branch August 30, 2024 02:53
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.

2 participants