Skip to content

Commit

Permalink
Merge pull request #213 from hyperledger-labs/ics-20-json
Browse files Browse the repository at this point in the history
ICS-20: Add JSON encoding support

Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele authored Oct 9, 2023
2 parents d9a90ca + 5d75e99 commit 4787197
Show file tree
Hide file tree
Showing 22 changed files with 1,104 additions and 1,742 deletions.
7 changes: 6 additions & 1 deletion .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ IBCTest:testBenchmarkSendPacket() (gas: 85940)
IBCTest:testBenchmarkUpdateMockClient() (gas: 129807)
IBCTest:testConnectionOpenInit() (gas: 496548)
IBCTest:testSendPacketInvalidTimestamp() (gas: 39167)
IBCTest:testToUint128((uint64,uint64)) (runs: 256, μ: 1047, ~: 1047)
IBCTest:testToUint128((uint64,uint64)) (runs: 256, μ: 1047, ~: 1047)
TestICS20:testAddressToHex(address) (runs: 256, μ: 23720, ~: 23889)
TestICS20:testHexToAddress(string) (runs: 256, μ: 4817, ~: 4829)
TestICS20:testIsEscapedString() (gas: 49914)
TestICS20:testMarshaling() (gas: 150062)
TestICS20:testParseAmount(uint256) (runs: 256, μ: 27089, ~: 21814)
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
run: make build

- name: Run tests
run: make FORGE_SNAPSHOT_OPTION=--check test
run: make test

- name: Linting
run: make lint
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[IBC](https://github.com/cosmos/ibc) implementations in Solidity.

**IBC compatibility:** [v4.0.0](https://github.com/cosmos/ibc-go/releases/tag/v4.0.0)
**IBC compatibility:** [v4](https://github.com/cosmos/ibc-go/releases/tag/v4.0.0)

This is available not only for Ethereum and Hyperledger Besu, but also for Polygon PoS and other blockchains that supports EVM-compatible.

Expand All @@ -15,7 +15,7 @@ NOTE: This is yet pre-beta non-production-quality software.

- Implementation of [ICS](https://github.com/cosmos/ibc/tree/master/spec/core)
- Implementation of [ICS-20](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer)
- [ERC-20 Token Transfer](./contracts/app/ICS20TransferBank.sol)
- [ERC-20 Token Transfer](./contracts/apps/20-transfer/ICS20TransferBank.sol)

## Documents

Expand All @@ -32,11 +32,18 @@ Here are some such examples:
- [Tendermint Light Client](https://github.com/datachainlab/tendermint-sol/tree/use-ibc-sol-hmy)
- [Mock Client](./contracts/clients/MockClient.sol)

## IBC relayer support

- [yui-relayer](https://github.com/datachainlab/yui-relayer): An IBC relayer for heterogeneous chains
- [ethereum-ibc-relay-chain](https://github.com/datachainlab/ethereum-ibc-relay-chain): A relay-chain module for EVM-compatible chains
- [ethereum-ibc-relay-prover](https://github.com/datachainlab/ethereum-ibc-relay-prover): A relay-prover module for Ethereum sync committee

## Related projects

- A demo of trustless bridge
- between Harmony and Cosmos(Tendermint): https://github.com/datachainlab/harmony-cosmos-bridge-demo
- between Celo and Cosmos: https://github.com/ChorusOne/celo-cosmos-bridge
- A demo of bridge between Cosmos(ibc-go) and Ethereum using IBC and LCP: https://github.com/datachainlab/cosmos-ethereum-ibc-lcp

## For Developers

Expand Down
53 changes: 28 additions & 25 deletions contracts/apps/20-transfer/ICS20Bank.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pragma solidity ^0.8.9;
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./ICS20Lib.sol";
import "./IICS20Bank.sol";

contract ICS20Bank is Context, AccessControl, IICS20Bank {
Expand All @@ -26,56 +26,59 @@ contract ICS20Bank is Context, AccessControl, IICS20Bank {
_setupRole(OPERATOR_ROLE, operator);
}

function balanceOf(address account, string calldata id) external view virtual returns (uint256) {
function balanceOf(address account, string calldata denom) external view virtual returns (uint256) {
require(account != address(0), "ICS20Bank: balance query for the zero address");
return _balances[id][account];
return _balances[denom][account];
}

function transferFrom(address from, address to, string calldata id, uint256 amount) external virtual override {
function transferFrom(address from, address to, string calldata denom, uint256 amount) external virtual override {
require(to != address(0), "ICS20Bank: transfer to the zero address");
require(
from == _msgSender() || hasRole(OPERATOR_ROLE, _msgSender()), "ICS20Bank: caller is not owner nor approved"
);

uint256 fromBalance = _balances[id][from];
uint256 fromBalance = _balances[denom][from];
require(fromBalance >= amount, "ICS20Bank: insufficient balance for transfer");
_balances[id][from] = fromBalance - amount;
_balances[id][to] += amount;
unchecked {
_balances[denom][from] = fromBalance - amount;
}
_balances[denom][to] += amount;
}

function mint(address account, string calldata id, uint256 amount) external virtual override {
function mint(address account, string calldata denom, uint256 amount) external virtual override {
require(hasRole(OPERATOR_ROLE, _msgSender()), "ICS20Bank: must have minter role to mint");
_mint(account, id, amount);
_mint(account, denom, amount);
}

function burn(address account, string calldata id, uint256 amount) external virtual override {
function burn(address account, string calldata denom, uint256 amount) external virtual override {
require(hasRole(OPERATOR_ROLE, _msgSender()), "ICS20Bank: must have minter role to mint");
_burn(account, id, amount);
_burn(account, denom, amount);
}

function addressToDenom(address tokenContract) public pure virtual override returns (string memory) {
return ICS20Lib.addressToHexString(tokenContract);
}

function deposit(address tokenContract, uint256 amount, address receiver) external virtual {
function deposit(address tokenContract, uint256 amount, address receiver) external virtual override {
require(tokenContract.isContract());
require(IERC20(tokenContract).transferFrom(_msgSender(), address(this), amount));
_mint(receiver, _genDenom(tokenContract), amount);
_mint(receiver, addressToDenom(tokenContract), amount);
}

function withdraw(address tokenContract, uint256 amount, address receiver) external virtual {
function withdraw(address tokenContract, uint256 amount, address receiver) external virtual override {
require(tokenContract.isContract());
_burn(_msgSender(), _genDenom(tokenContract), amount);
_burn(_msgSender(), addressToDenom(tokenContract), amount);
require(IERC20(tokenContract).transfer(receiver, amount));
}

function _mint(address account, string memory id, uint256 amount) internal virtual {
_balances[id][account] += amount;
function _mint(address account, string memory denom, uint256 amount) internal virtual {
_balances[denom][account] += amount;
}

function _burn(address account, string memory id, uint256 amount) internal virtual {
uint256 accountBalance = _balances[id][account];
function _burn(address account, string memory denom, uint256 amount) internal virtual {
uint256 accountBalance = _balances[denom][account];
require(accountBalance >= amount, "ICS20Bank: burn amount exceeds balance");
_balances[id][account] = accountBalance - amount;
}

function _genDenom(address tokenContract) internal pure virtual returns (string memory) {
return Strings.toHexString(tokenContract);
unchecked {
_balances[denom][account] = accountBalance - amount;
}
}
}
Loading

0 comments on commit 4787197

Please sign in to comment.