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

Problem: evm contract can't call native module message #45

Merged
merged 12 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

- [cronos#11](https://github.com/crypto-org-chain/cronos/pull/11) embed gravity bridge module


- [cronos#45](https://github.com/crypto-org-chain/cronos/pull/45) Allow evm contract to call bank send and gravity send

*August 19, 2021*

Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ GOPATH ?= $(shell $(GO) env GOPATH)
BINDIR ?= ~/go/bin


all: build
build: go.sum
@go build -mod=readonly $(BUILD_FLAGS) $(BUILD_TAGS) -o $(BUILDDIR)/cronosd ./cmd/cronosd

Expand All @@ -15,6 +16,8 @@ install: go.sum
test:
@go test -v -mod=readonly $(PACKAGES) -coverprofile=$(COVERAGE) -covermode=atomic

.PHONY: build install test

###############################################################################
### Linting ###
###############################################################################
Expand Down
5 changes: 5 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ func New(

app.GravityKeeper = *gravityKeeper.SetHooks(app.CronosKeeper)

app.EvmKeeper.SetHooks(cronosmodulekeeper.NewLogProcessEvmHook(
cronosmodulekeeper.NewNativeTransferHandler(app.BankKeeper, app.CronosKeeper),
cronosmodulekeeper.NewEthereumTransferHandler(gravitykeeper.NewMsgServerImpl(app.GravityKeeper), app.CronosKeeper),
))

// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks(
Expand Down
16 changes: 15 additions & 1 deletion contracts/src/ModuleCRC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ import "ds-token/token.sol";
contract ModuleCRC20 is DSToken {
// sha256('cronos')[:20]
address constant module_address = 0x6526B48f897f6e08067dF00A1821d783cbC2af8b;
string denom;

constructor(string memory denom, uint8 decimals_) DSToken(denom) public {
event __CronosEthereumTransfer(address recipient, uint256 amount, uint256 bridge_fee);

constructor(string memory denom_, uint8 decimals_) DSToken(denom) public {
decimals = decimals_;
denom = denom_;
}

function native_denom() public view returns (string memory) {
return denom;
}

function mint_by_cronos_module(address addr, uint amount) public {
Expand All @@ -23,4 +31,10 @@ contract ModuleCRC20 is DSToken {
totalSupply = sub(totalSupply, amount);
emit Burn(addr, amount);
}

// send to ethereum through gravity bridge
function send_to_ethereum(address recipient, uint amount, uint bridge_fee) public {
burn(msg.sender, add(amount, bridge_fee));
emit __CronosEthereumTransfer(recipient, amount, bridge_fee);
}
}
1 change: 1 addition & 0 deletions contracts/src/ModuleCRC20.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ contract ModuleCRC20Test is DSTest {

function test_basic_sanity() public {
assertEq(uint(token.decimals()), uint(0));
assertEq(token.native_denom(), "gravity0x0");
}

function testFail_mint_by_cronos_module() public {
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ go 1.16

require (
github.com/armon/go-metrics v0.3.9
github.com/cosmos/cosmos-sdk v0.43.0
github.com/cosmos/cosmos-sdk v0.44.0
github.com/cosmos/ibc-go v1.0.1
github.com/ethereum/go-ethereum v1.10.3
github.com/gogo/protobuf v1.3.3
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/peggyjv/gravity-bridge/module v0.1.21
github.com/peggyjv/gravity-bridge/module v0.2.0
github.com/spf13/cast v1.4.1
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
github.com/tendermint/spm v0.0.0-20210524110815-6d7452d2dc4a
github.com/tendermint/tendermint v0.34.12
github.com/tendermint/tm-db v0.6.4
github.com/tharsis/ethermint v0.4.2-0.20210831155846-516ffe2bf176
github.com/tharsis/ethermint v0.4.2-0.20210902174739-5fac39db38ed
google.golang.org/genproto v0.0.0-20210825212027-de86158e7fda
google.golang.org/grpc v1.40.0
gopkg.in/yaml.v2 v2.4.0
Expand Down
11 changes: 6 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosmos/cosmos-sdk v0.43.0 h1:l2GXJMDVtJyHb35pDUCw+uyr6eZtBo8vt+7PSsq+Fjo=
github.com/cosmos/cosmos-sdk v0.43.0/go.mod h1:ctcrTEAhei9s8O3KSNvL0dxe+fVQGp07QyRb/7H9JYE=
github.com/cosmos/cosmos-sdk v0.44.0 h1:eOSjACNtTnThEJ62IsS+pMm3OIU6hgMVqrp4TZClLZo=
github.com/cosmos/cosmos-sdk v0.44.0/go.mod h1:orG0jzFJ2KsDfzLd/X0JSOMzF4Oxc/BQz2GkcYF4gRE=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
Expand Down Expand Up @@ -748,8 +749,8 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/peggyjv/gravity-bridge/module v0.1.21 h1:5QBK682gf67vQoCpedeJYzTPPLWvZJtmqLxj7lWEJ+o=
github.com/peggyjv/gravity-bridge/module v0.1.21/go.mod h1:Key1D2z/KaJ5A206L3EQW6RWo4q8w+Jpl+p5HMm896g=
github.com/peggyjv/gravity-bridge/module v0.2.0 h1:1sAoILN/KKOSRlrVEu2RzAUYNm5NyNRbA0LnXJSNejY=
github.com/peggyjv/gravity-bridge/module v0.2.0/go.mod h1:gixjqIjdEb0CC0Kp4bLaJRoFSMG+irz3qU6gWwmNHik=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
Expand Down Expand Up @@ -953,8 +954,8 @@ github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs
github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8=
github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ=
github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw=
github.com/tharsis/ethermint v0.4.2-0.20210831155846-516ffe2bf176 h1:DcRmsQNJFpbXF35HLsFgoyuuCFlSEWQ8R5/dGxn9aY0=
github.com/tharsis/ethermint v0.4.2-0.20210831155846-516ffe2bf176/go.mod h1:xN960Qi1siaDDIJjTTEwCF03vXD7KlRUG63YMMH8MpU=
github.com/tharsis/ethermint v0.4.2-0.20210902174739-5fac39db38ed h1:tJoRSbvnKkueMUuFOgfGK7svOjvnkqNP5STRgsTF8As=
github.com/tharsis/ethermint v0.4.2-0.20210902174739-5fac39db38ed/go.mod h1:Vvn8Ml0LJ3NsDGLnxzwHp9lnrr6j3r2DHutR10iDyME=
github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
Expand Down
18 changes: 9 additions & 9 deletions gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -886,12 +886,12 @@
sha256 = "0nxbn0m7lr4dg0yrwnvlkfiyg3ndv8vdpssjx7b714nivpc6ar0y"

["github.com/cosmos/cosmos-sdk"]
sumVersion = "v0.43.0"
sumVersion = "v0.44.0"
["github.com/cosmos/cosmos-sdk".fetch]
type = "git"
url = "https://github.com/cosmos/cosmos-sdk"
rev = "3f8596c1955e40ef30e4abcd06f2237d132db3a9"
sha256 = "1fgi8xq4k7bislfchl8hz18iwf37ppkp5w471v5h4axq4xynpsmy"
rev = "ccc5245c3a1b2e5f1f584e9395fc571a1d19d989"
sha256 = "1vh48mwp8w21a3i71alwn56rlm8ip2na5mm7jpsj43d9d915phxp"

["github.com/cosmos/go-bip39"]
sumVersion = "v1.0.0"
Expand Down Expand Up @@ -2965,13 +2965,13 @@
sha256 = "0f146yjqwx2mr110kl8scjhqd08hys7vr5z0d0a3lskb6yy22gfg"

["github.com/peggyjv/gravity-bridge/module"]
sumVersion = "v0.1.21"
sumVersion = "v0.2.0"
relPath = "module"
["github.com/peggyjv/gravity-bridge/module".fetch]
type = "git"
url = "https://github.com/peggyjv/gravity-bridge"
rev = "755156abff254420eec2c4e54fb6e8d189556ee2"
sha256 = "1fjkq0jv42pq7fsah4chk2d1xkrdnkb9x52lkyagzlykw08ywcvr"
rev = "8af32db2883af08acd35bd76703eac39ab283eaa"
sha256 = "1rk5xca5zvk3srxsfa8482hbimf1mcdl5dksf2b5vgrmim4v3vn8"

["github.com/pelletier/go-toml"]
sumVersion = "v1.9.3"
Expand Down Expand Up @@ -3542,12 +3542,12 @@
sha256 = "1sgjf2vaq554ybc0cwkzn17cz2ibzph2rq0dgaw21c2hym09437x"

["github.com/tharsis/ethermint"]
sumVersion = "v0.4.2-0.20210831155846-516ffe2bf176"
sumVersion = "v0.4.2-0.20210902174739-5fac39db38ed"
["github.com/tharsis/ethermint".fetch]
type = "git"
url = "https://github.com/tharsis/ethermint"
rev = "516ffe2bf1765c62a6cdabf0384410933b431e65"
sha256 = "096rm0ibagl6ilhakpm7qb6g521m3jjif738pgzx6ih1mw0g5qi1"
rev = "5fac39db38ed302af421e56f321b979200332287"
sha256 = "1l64nimbmfxv06qn3b3356maan8npn0hlnqxd1iv4sqdganvkbra"

["github.com/tidwall/gjson"]
sumVersion = "v1.6.7"
Expand Down
22 changes: 18 additions & 4 deletions integration_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,27 @@ def __exit__(self, _1, _2, _3):
yield SuspendGuard()


@pytest.fixture(scope="session")
def cronos(tmp_path_factory):
path = tmp_path_factory.mktemp("cronos")
yield from setup_cronos(path, 26650)


@pytest.fixture(scope="session")
def geth(tmp_path_factory):
path = tmp_path_factory.mktemp("geth")
yield from setup_geth(path, 8545)


@pytest.fixture(scope="session", params=["cronos", "geth"])
def cluster(request, tmp_path_factory):
def cluster(request, cronos, geth):
"""
run on both cronos and geth
"""
provider = request.param
path = tmp_path_factory.mktemp(provider)
if provider == "cronos":
yield from setup_cronos(path, 26650)
yield cronos
elif provider == "geth":
yield from setup_geth(path, 8545)
yield geth
else:
raise NotImplementedError
7 changes: 7 additions & 0 deletions integration_tests/contracts/contracts/TestERC20A.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ pragma solidity ^0.6.6;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TestERC20A is ERC20 {
event __CronosNativeTransfer(address recipient, uint256 amount);
event __CronosEthereumTransfer(address recipient, uint256 amount, uint256 bridge_fee);

constructor() public ERC20("Bitcoin MAX", "MAX") {
_mint(msg.sender, 100000000000000000000000000);
}

function test_native_transfer(uint amount) public {
emit __CronosNativeTransfer(msg.sender, amount);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't u have to burn the amount?

imo __CronosNativeTransfer is not clear for the operation. A transfer imply an origin and a destination.

Here it seems that you are either converting or minting?

It seems more that you are con

Copy link
Collaborator Author

@yihuang yihuang Sep 8, 2021

Choose a reason for hiding this comment

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

This is solely for testing the native call, the semantic of the call is to transfer mapped native token from contract address to recipient.
But because we can't setup token mapping in e2e testing right now, so the test itself is not complete yet (there's a TODO in that).

This is not the e2e testing for the complete bridge yet.

Copy link
Collaborator

Choose a reason for hiding this comment

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

so maybe __CronosCosmosConvert or __CronosCosmosMint?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

so maybe __CronosCosmosConvert or __CronosCosmosMint?

“Native” stands for native token, “Transfer” is also self explanatory I believe?

Copy link
Collaborator

@thomas-nguy thomas-nguy Sep 8, 2021

Choose a reason for hiding this comment

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

is also self explanatory I believe?

I dont think so..
"Native" has barely any meaning without context. And using "Transfer" without specifying a sender and destination sounds weird.

If we can't find a proper short term to describe the operation, I would prefer to be very explicit and call the event
"__CronosSendFromContractToAccount(receiver, amount)" instead...

Mind that most smart contract developer won't have deep knowledge about the internal implementation, or cosmos implementation

Copy link
Contributor

Choose a reason for hiding this comment

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

When I think about it again, can we say "From" is implied because the action is "Send" and we are executing a contract? It is the "Subject" (what token) and "To" that's unclear.

So

___CronosSendXToAccount // Account or Native Account? need to address in the terminology issue
___CronosSendXToEthereum // Send X (From the contract account) To Ethereum
___CronosSendXToIBCChannel
// Similar to Gravity Bridge `SendToCosmos` but be more explicit about the token type

p.s. Having "From" is no harm, my motive is if we think event name is too long then we can think about to trim it or not. I am okay to include it and be more explicit. (Is there any restricting on event name length?)

Copy link
Collaborator Author

@yihuang yihuang Sep 9, 2021

Choose a reason for hiding this comment

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

When I think about it again, can we say "From" is implied because the action is "Send" and we are executing a contract? It is the "Subject" (what token) and "To" that's unclear.

So

___CronosSendXToAccount // Account or Native Account? need to address in the terminology issue
___CronosSendXToEthereum // Send X (From the contract account) To Ethereum
___CronosSendXToIBCChannel
// Similar to Gravity Bridge `SendToCosmos` but be more explicit about the token type

p.s. Having "From" is no harm, my motive is if we think event name is too long then we can think about to trim it or not. I am okay to include it and be more explicit. (Is there any restricting on event name length?)

Looks good to me.
And let's use NativeTokens for X for now? or Coins?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe 'X' can be omitted now?

__CronosSendToAccount
__CronosSendToEthereum
__CronosSendToIBCChannel

Even if we add NativeToken or Coins, it is not clear which coin is it. We need a proper term to designate the "Coin associated with the contract"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe 'X' can be omitted now?

__CronosSendToAccount
__CronosSendToEthereum
__CronosSendToIBCChannel

Even if we add NativeToken or Coins, it is not clear which coin is it. We need a proper term to designate the "Coin associated with the contract"

Looks good too, I suppose we'll have detailed documentation about them as part of the CRC20 standard.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

#62
opened issue and documented decision so far in it.

}
}
5 changes: 1 addition & 4 deletions integration_tests/cosmoscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,6 @@ def transfer(self, from_, to, coins, generate_only=False, fees=None):
"-y",
"--generate-only" if generate_only else None,
home=self.data_dir,
keyring_backend="test",
chain_id=self.chain_id,
node=self.node_rpc,
fees=fees,
)
)
Expand Down Expand Up @@ -943,7 +940,7 @@ def send_to_ethereum(self, from_, receiver, coins, fee):
self.raw(
"tx",
"gravity",
"send-to-etheruem",
"send-to-ethereum",
receiver,
coins,
fee,
Expand Down
33 changes: 32 additions & 1 deletion integration_tests/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
from .utils import ADDRS
from pathlib import Path

from .utils import ADDRS, deploy_contract


def test_basic(cluster):
w3 = cluster.w3
assert w3.eth.chain_id == 777
assert w3.eth.get_balance(ADDRS["community"]) == 10000000000000000000000


def test_native_call(cronos):
"""
test contract native call on cronos network
- deploy test contract
- run native call, expect failure, becuase no native fund in contract
- send native tokens to contract account
- run again, expect success and check balance
"""
w3 = cronos.w3
contract = deploy_contract(
w3,
Path(__file__).parent
/ "contracts/artifacts/contracts/TestERC20A.sol/TestERC20A.json",
)

amount = 100

# the coinbase in web3 api is the same address as the validator account in
# cosmos api

# expect failure, because contract is not connected with native denom yet
# TODO complete the test after gov managed token mapping is implemented.
txhash = contract.functions.test_native_transfer(amount).transact(
{"from": w3.eth.coinbase}
)
receipt = w3.eth.wait_for_transaction_receipt(txhash)
assert receipt.status == 0, "should fail"
7 changes: 6 additions & 1 deletion integration_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,19 @@ def contract_address(addr, nonce):


def decode_bech32(addr):
previx, bz = bech32.bech32_decode(addr)
_, bz = bech32.bech32_decode(addr)
return HexBytes(bytes(bech32.convertbits(bz, 5, 8)))


def bech32_to_eth(addr):
return decode_bech32(addr).hex()


def eth_to_bech32(addr, prefix="ethm"):
bz = bech32.convertbits(HexBytes(addr), 8, 5)
return bech32.bech32_encode(prefix, bz)


class DelegateKeysSignMsg(ProtoEntity):
validator_address = Field("string", 1)
nonce = Field("uint64", 2)
Expand Down
Loading