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: add ICS20 App on IBC #793

Conversation

sdpisreddevil
Copy link
Collaborator

@sdpisreddevil sdpisreddevil commented Dec 13, 2023

Description

ICS20 Transfer

Commit Message

type: commit message

see the guidelines for commit messages.

Changelog Entry

version: <log entry>

Checklist

  • I have performed a self-review of my own code
  • I have documented my code in accordance with the documentation guidelines
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have run the unit tests
  • I only have one commit (if not, squash them into one commit).
  • I have a descriptive commit message that adheres to the commit message guidelines
  • I have added version bump label on PR.

Please review the CONTRIBUTING.md file for detailed contributing guidelines.

@sdpisreddevil sdpisreddevil self-assigned this Dec 13, 2023
@sdpisreddevil sdpisreddevil marked this pull request as draft December 13, 2023 02:56
@sdpisreddevil sdpisreddevil changed the title Add ICS20 App on IBC feat: add ICS20 App on IBC Dec 13, 2023
byte[] denomPrefix = getDenomPrefix(packet.data.sourcePort, packet.data.sourceChannel);
byte[] denom = packet.data.denom.getBytes();
if (denom.length >= denomPrefix.length) {
// denom slicing todo
Copy link
Collaborator

Choose a reason for hiding this comment

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

wouldnot length of denom be always greater than denomPrefix? .i think we would need to compare denom prefix with packet sourcePort and sourceChannel to determine if sender is source or sink then burn token if sender is source.

@External
public void onAcknowledgementPacket(byte[] calldata, byte[] acknowledgement, Address relayer) {
Context.println("onAcknowledgementPacket");
// Context.require(Context.getCaller().equals(getIBCAddress()), "caller is not handler");
Copy link
Collaborator

Choose a reason for hiding this comment

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

we can decode packet from calldata ... and lets rename it to packetBytes as well.

}

@External
public void onTimeoutPacket(Packet packet, byte[] proofHeight, byte[] proof, BigInteger nextSequenceRecv) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

we need to refund on packet timeout as well.

byte[] packetData = ICS20Lib.marshalJson(denom,amount, ICS20Transfer._encodeSender(caller),receiver);


// ibcHandler.sendPacket(sourcePort, sourceChannel, Height., timeoutHeight);
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think we can merge this with ICS20Transfer and treat it as the entry contract. Is there any reason to separate this out?

@sdpisreddevil sdpisreddevil marked this pull request as ready for review February 12, 2024 07:37
@AntonAndell
Copy link
Collaborator

@nightowl121 Should we mabye have the bank implment IRC31? where a denom gets assigned a ID? At the current state these tokens cannot be used by contracts at all.

@sdpisreddevil sdpisreddevil linked an issue Feb 13, 2024 that may be closed by this pull request
Context.require(version.equals(ICS20_VERSION), "version should be same with ICS20_VERSION");
Channel.Counterparty counterparty = Channel.Counterparty.decode(counterpartyPb);
destinationPort.set(channelId, counterparty.getPortId());
channelEscrowAddresses.set(channelId, Context.getAddress());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could this logic not be completely omitted, is there any scenario where escrow won't be this contract?

Comment on lines +165 to +168
if (denom.length >= denomPrefix.length && Ops.hasPrefix(denom, denomPrefix)) {
Context.require(_mint(Address.fromString(data.sender), data.denom, data.amount), "ICS20: mint failed");
} else {
Context.require(_transferFrom(getEscrowAddress(sourceChannel), Address.fromString(data.sender), data.denom, data.amount), "ICS20: transfer failed");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove require on _mint and _transfer from and convert those functions to void

Comment on lines +186 to +189
boolean _burn(Address account, String denom, BigInteger amount) {
Context.call(bank.get(), "burn", account, denom, amount);
return true;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

make void

Comment on lines +191 to +195
boolean _transferICX(Address receiver, BigInteger amount) {
Context.require(Context.getBalance(Context.getAddress()).compareTo(amount) >= 0, "ICS20App: insufficient balance for transfer");
Context.transfer(receiver, amount);
return true;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Make void

Comment on lines +201 to +211
protected static boolean _decodeReceiver(String receiver) {
boolean flag;
try {
Address.fromString(receiver);
flag = true;
} catch (Exception e) {
flag = false;

}
return flag;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
protected static boolean _decodeReceiver(String receiver) {
boolean flag;
try {
Address.fromString(receiver);
flag = true;
} catch (Exception e) {
flag = false;
}
return flag;
}
protected static boolean _decodeReceiver(String receiver) {
try {
Address.fromString(receiver);
flag = true;
} catch (Exception e) {
return false;
}
}

}

@External
public byte[] onRecvPacket(byte[] packet, Address relayer) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this fucntion is not allowed to fail, perhaps create a internal function and wrap this in a try catch to always return failed ack in case of failure

Address caller = Context.getCaller();
if (denom.equals("icx")) {
Context.require(Context.getValue().compareTo(BigInteger.ZERO) > 0, "ICS20App: icx transfer failed");
Context.require(Context.getValue().compareTo(amount) == 0, "ICS20App: icx value is not equal to amount sent");
Copy link
Collaborator

Choose a reason for hiding this comment

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

user .equals

Comment on lines +47 to +49
Context.require(_transferFrom(caller, ICS20Transfer.getEscrowAddress(sourceChannel), denom, amount), "ICS20App: transfer failed");
} else {
Context.require(_burn(caller, denom, amount), "ICS20App: Burn failed");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove require since the wont work

byte[] denomPrefix = ICS20Transfer.getDenomPrefix(sourcePort, sourceChannel);
String denomText = new String(denomPrefix);
if (!denom.startsWith(denomText)) {
Context.require(_transferFrom(caller, ICS20Transfer.getEscrowAddress(sourceChannel), denom, amount), "ICS20App: transfer failed");
Copy link
Collaborator

Choose a reason for hiding this comment

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

When is this case used on ICON?

Comment on lines +88 to +94
@External
public void deposit(Address tokenContract, BigInteger amount, Address receiver) {
Context.require(tokenContract.isContract(), TAG + ": tokenContract is not a contract");
Context.call(tokenContract, "transferFrom", Context.getCaller(), Context.getAddress(), amount);
_mint(receiver, tokenContract.toString(), amount);
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

What tokens are these?

Copy link
Collaborator

Choose a reason for hiding this comment

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

To support ICON tokens it should be done via tokenFallback

@AntonAndell
Copy link
Collaborator

I am not sure what to do about the token standard though, if we want IRC31 or go with a IRC2 standard so that tokens can be used as normal tokens.

@nightowl121
Copy link
Collaborator

@nightowl121 Should we mabye have the bank implment IRC31? where a denom gets assigned a ID? At the current state these tokens cannot be used by contracts at all.

Yeah it would be helpful if we make it compatible with an existing standard or else we would have to propose a new standard to be used by the contracts.

@izyak izyak changed the base branch from main to ics-20-irc20-support March 14, 2024 05:54
@izyak
Copy link
Collaborator

izyak commented Mar 14, 2024

Merge this PR to another branch to start working on this new branch for IRC2 support

@izyak izyak merged commit 4007678 into icon-project:ics-20-irc20-support Mar 14, 2024
5 of 8 checks passed
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.

ICS20 Integration
7 participants