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

feat: modify batcher contract to support erc20 sendMany #192

Merged
merged 1 commit into from
Feb 4, 2025

Conversation

kamleshmugdiya
Copy link
Contributor

Ticket: COIN-2782

Copy link
Contributor

@gianchandania gianchandania left a comment

Choose a reason for hiding this comment

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

Please add tests for the method

address[] calldata recipients,
uint256[] calldata amounts
) external lockCall {
require(recipients.length == amounts.length, "Length mismatch");
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should add other validations which are there in batch method here as well

require(recipients.length != 0, 'Must send to at least one person');
require(recipients.length < 256, 'Too many recipients');

should check what this number should be instead of 256

Copy link
Contributor

Choose a reason for hiding this comment

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

Also length mismatch error is bit ambiguous. let's make this error message same as batch method

Copy link
Contributor Author

Choose a reason for hiding this comment

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

kept the limit dynamic since it can be different for different chains.
added a function changeBatchTransferLimit to change the limit.

) external lockCall {
require(recipients.length == amounts.length, "Length mismatch");
for (uint256 i = 0; i < recipients.length; i++) {
TransferHelper.safeTransferFrom(token, msg.sender, recipients[i], amounts[i]);
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally there should not be a case of partial success, either we send successfully to all the recipients, or none of the transfer should go through.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to do partial success with giving less approval.
approval given was 20.
tried to send 30 here.
but it failed.

can you suggest some other way to try where partial success can be possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as suggested, I tried to send to 5 recipients while giving the gas limit for only 2.
the tx failed on chain.
https://holesky.etherscan.io/tx/0x42d64222124a57e5ee7135be7794fcf3d81df5563be3b55cb5a4df81803f2bf9

) external lockCall {
require(recipients.length != 0, 'Must send to at least one person');
require(recipients.length == amounts.length, "Unequal recipients and values");
for (uint256 i = 0; i < recipients.length; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
for (uint256 i = 0; i < recipients.length; i++) {
for (uint8 i = 0; i < recipients.length; i++) {

Copy link
Contributor

Choose a reason for hiding this comment

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

https://medium.com/coinmonks/mastering-solidity-require-and-custom-errors-in-ethereum-contracts-b491565f1592

You can also change the contract to use custom errors instead of require statements

Copy link
Contributor Author

Choose a reason for hiding this comment

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

used uint16.
also added custom errors.

@kamleshmugdiya
Copy link
Contributor Author

Please add tests for the method

added few tests.

Comment on lines +9 to +11
error EmptyRecipientsList();
error UnequalRecipientsAndValues();
error TooManyRecipients(uint256 provided, uint256 limit);
error TokenTransferFailed(address token, address from, address to, uint256 amount);
Copy link
Contributor

Choose a reason for hiding this comment

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

Add comments following the natspec format for everything

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: comments on errros

contracts/Batcher.sol Outdated Show resolved Hide resolved
test/batcher.js Fixed Show fixed Hide fixed
Copy link
Contributor

@sachushaji sachushaji left a comment

Choose a reason for hiding this comment

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

Good Work!!

Comment on lines +9 to +11
error EmptyRecipientsList();
error UnequalRecipientsAndValues();
error TooManyRecipients(uint256 provided, uint256 limit);
error TokenTransferFailed(address token, address from, address to, uint256 amount);
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: comments on errros

Comment on lines +800 to +802
await checkBalance(sender, 500);
await checkBalance(recipients[0], 0);
await checkBalance(recipients[1], 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: you can use promise.all

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@mullapudipruthvik mullapudipruthvik left a comment

Choose a reason for hiding this comment

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

LGTM
Have we figured out the owner and how do we interact with the contract?


IERC20 safeToken = IERC20(token);
for (uint16 i = 0; i < recipients.length; i++) {
safeToken.safeTransferFrom(msg.sender, recipients[i], amounts[i]);
Copy link
Contributor

Choose a reason for hiding this comment

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

should we allow 0 value transfers ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will handle it here.
https://bitgoinc.atlassian.net/browse/COIN-3005

what is the expected behaviour?

  1. should it skip the 0 value transfers and continue with other transfers?
  2. fail entirely (keeping it atomic).

@kamleshmugdiya
Copy link
Contributor Author

LGTM Have we figured out the owner and how do we interact with the contract?

Not sure about the owner.
I am thinking we will need a script and a workflow (since the owner will be bitgo key) to modify the limit.

@kamleshmugdiya kamleshmugdiya merged commit a503f9f into master Feb 4, 2025
4 checks passed
@kamleshmugdiya kamleshmugdiya deleted the COIN-2782 branch February 4, 2025 05:22
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.

4 participants