Skip to content

Commit

Permalink
draft for adr-010
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-nguy committed Oct 2, 2023
1 parent 79c911c commit 0dadeb8
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 11 deletions.
23 changes: 12 additions & 11 deletions docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ To suggest an ADR, please make use of the [ADR template](./adr-template.md) prov

## Table of Contents

| ADR \# | Description | Status |
|---------------------|----------------------------------------------------------------------------|----------|
| [001](./adr-001.md) | Disable Gravity Bridge at Genesis | Accepted |
| [002](./adr-002.md) | Use a custom fork of ibc-go | Accepted |
| [003](./adr-003.md) | Add Fee Market Module | Accepted |
| [004](./adr-004.md) | Tokens conversion in Cronos | Accepted |
| [005](./adr-005.md) | Cross-chain Validation for Gravity Bridge | Rejected |
| [006](./adr-006.md) | Migrating CRC20 contract to CRC21 standard | Rejected |
| [007](./adr-007.md) | Generic event format for evm-hook actions | Accepted |
| [008](./adr-008.md) | Denom and Contract Mapping Enhancement for Bi-Directional Token Conversion | Accepted |
| [009](./adr-009.md) | Permissioned addresses in Cronos | Accepted |
| ADR \# | Description | Status |
|----------------------|----------------------------------------------------------------------------|----------|
| [001](./adr-001.md) | Disable Gravity Bridge at Genesis | Accepted |
| [002](./adr-002.md) | Use a custom fork of ibc-go | Accepted |
| [003](./adr-003.md) | Add Fee Market Module | Accepted |
| [004](./adr-004.md) | Tokens conversion in Cronos | Accepted |
| [005](./adr-005.md) | Cross-chain Validation for Gravity Bridge | Rejected |
| [006](./adr-006.md) | Migrating CRC20 contract to CRC21 standard | Rejected |
| [007](./adr-007.md) | Generic event format for evm-hook actions | Accepted |
| [008](./adr-008.md) | Denom and Contract Mapping Enhancement for Bi-Directional Token Conversion | Accepted |
| [009](./adr-009.md) | Permissioned addresses in Cronos | Accepted |
| [0010](./adr-010.md) | Custom precompiled for app-chain | Accepted |
133 changes: 133 additions & 0 deletions docs/architecture/adr-010.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# ADR 01-: Custom precompiled for app-chain

## Changelog
* 2023-10-02: first draft

## Context

Cronos is an EVM-compatible built on Cosmos SDK. The "ethermint" module allows a full compatibility and interoperability with Ethereum. However, it comes with the sacrifice of cosmos native features or cosmos interchain features (IBC)
as end-users are not able to access them through an ethereum transaction format. The solution is to provide precompile, allowing users to access to cosmos features through smart contract.
A precompiled behave like smart contracts, it is designed by an addressed and can be invoked by other smart contracts. The difference is that its execution is not inside a smart contract.
App-chain logic can be embedded to the pre-compiled so that it could be used to expose cosmos native feature to the EVM layer.


## Decision

### Fork go-ethereum for stateful precompiled support

One of the major difficulties in supporting pre-compiled is the lack of flexibility in geth for defining custom precompiled and its non-ability to modify the state.
We made the choice of forking geth and implement additional interfaces and logic so that app-chain can define its own precompiled.

The PR [#7](https://github.com/evmos/go-ethereum/pull/7) implements the ability to set custom precompiled to the EVM.
while this PR [#10](https://github.com/evmos/go-ethereum/pull/10) allows the precompiled to modify the state (for stateful precompiled)

### Implement pre-compiled for cosmos native module

We provide pre-compile for cosmos native module such as bank or staking.

The input and output of methods are mapped with those defined cosmos native transactions

```solidity
interface IBankModule {
function mint(address,uint256) external payable returns (bool);
function balanceOf(address,address) external view returns (uint256);
function burn(address,uint256) external payable returns (bool);
function transfer(address,address,uint256) external payable returns (bool);
}
interface IStakingModule {
# to be completed
}
```

To call a precompiled, create an instance of the module interface with the precompiled address.
The methods are ABI encoded, and can be called directly as calling the function through the interface:


```solidity
address constant bankContract = 0x0000000000000000000000000000000000000064;
IBankModule bank = IBankModule(bankContract);
bank.transfer(msg.sender, recipient, amount);
```


### Implement pre-compiled for cosmos interchain communication

One of the benefits of supporting precompiled for IBC is that it would be possible to track the change of state triggered by the ibc transaction with ethereum receipts.

For that reason we are exposing all relayer related actions to the evm layer. An action is defined by a 4 bytes prefix.

```go

const (
prefixSize4Bytes = 4
// Client
prefixCreateClient = iota + 1
prefixUpdateClient
prefixUpgradeClient
prefixSubmitMisbehaviour
// Connection
prefixConnectionOpenInit
prefixConnectionOpenTry
prefixConnectionOpenAck
prefixConnectionOpenConfirm
// Channel
prefixChannelOpenInit
prefixChannelOpenTry
prefixChannelOpenAck
prefixChannelOpenConfirm
prefixChannelCloseInit
prefixChannelCloseConfirm
prefixRecvPacket
prefixAcknowledgement
prefixTimeout
prefixTimeoutOnClose
)

```

-> go relayer changes

For ICA, we are following the same standard as for the cosmos module

The ICA precompiled interface is defined by:

```solidity
interface IICAModule {
event SubmitMsgsResult(uint64 seq);
function registerAccount(string calldata connectionID, string calldata version) external payable returns (bool);
function queryAccount(string calldata connectionID, address addr) external view returns (string memory);
function submitMsgs(string calldata connectionID, bytes calldata data, uint256 timeout) external payable returns (uint64);
}
```

In case of ICA, it is important to receives the result of the transaction `submitMsgs` for the user or the smart contract to respond accordingly.
The function `submitMsgs` return a sequence number that can be used by the user or smart contract to track the state of the msg using the ICA callback precompiled.


```solidity
interface IICACallback {
function onPacketResultCallback(uint64 seq, bool ack) external payable returns (bool);
}
```


### Precompiled gas cost

A precompiled acts as an op-code in the evm layer and has a constant cost. Because a stateful precompiled can change the state, it is much harder to define a specific cost for an action.
To be fair, we are evaluating the cost of a pre-compile based on the past history and we are planning to tune the cost further in the future.

## Further discussions


## References

* https://github.com/crypto-org-chain/cronos/pull/837
* https://github.com/crypto-org-chain/cronos/pull/1163
* https://github.com/crypto-org-chain/cronos/pull/1014

0 comments on commit 0dadeb8

Please sign in to comment.