Skip to content

Commit

Permalink
Merge pull request #4 from lukso-network/unit-tests
Browse files Browse the repository at this point in the history
Unit tests
  • Loading branch information
CJ42 authored Oct 21, 2024
2 parents 9b63dd3 + bb2828c commit dd7d601
Show file tree
Hide file tree
Showing 9 changed files with 440 additions and 103 deletions.
3 changes: 1 addition & 2 deletions .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
"extends": "solhint:recommended",
"rules": {
"code-complexity": ["error", 8],
"compiler-version": ["error", ">=0.8.25"],
"compiler-version": ["error", ">=0.8.0"],
"func-name-mixedcase": "off",
"func-visibility": ["error", { "ignoreConstructors": true }],
"max-line-length": ["error", 120],
"named-parameters-mapping": "warn",
"no-console": "off",
"not-rely-on-time": "off",
Expand Down
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@
[license]: https://opensource.org/licenses/MIT
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg

This repo is the LSP7 version of the [`HypERC20`] and [`HypERC20Collateral`] of `@hyperlane-xyz/core` package. They are used to bridge tokens between the Ethereum and LUKSO chains using the [Hashi Bridge](https://crosschain-alliance.gitbook.io/hashi).
This repo is the LSP7 version of the [`HypERC20`] and [`HypERC20Collateral`] of `@hyperlane-xyz/core` package. They are
used to bridge tokens between the Ethereum and LUKSO chains using the
[Hashi Bridge](https://crosschain-alliance.gitbook.io/hashi).

For more details on the **architecture and bridging flow**, see the [**`docs/`**](./docs/README.md) folder.

### Examples of bridged tokens

- ETH -> LUKSO: https://explorer.hyperlane.xyz/message/0x53a383e32fdb68748c8af5c86be3669e58eadc377db2a9f420826cb9474dd55c

- LUKSO -> ETH: https://explorer.hyperlane.xyz/message/0xf9c86a22e7b5584fc87a9d4ffc39f967a8745cd28b98ed2eaeb220c43996c4ca
- ETH -> LUKSO:
https://explorer.hyperlane.xyz/message/0x53a383e32fdb68748c8af5c86be3669e58eadc377db2a9f420826cb9474dd55c

- LUKSO -> ETH:
https://explorer.hyperlane.xyz/message/0xf9c86a22e7b5584fc87a9d4ffc39f967a8745cd28b98ed2eaeb220c43996c4ca

## Getting Started

Expand All @@ -45,7 +48,6 @@ This is how to install dependencies:

Note that OpenZeppelin Contracts is pre-installed, so you can follow that as an example.


### Sensible Defaults

This template comes with a set of sensible default configurations for you to use. These defaults can be found in the
Expand All @@ -67,7 +69,6 @@ This is a list of the most frequently needed commands.

### Build & Compile


```sh
# Build the contracts:
forge build
Expand Down Expand Up @@ -100,18 +101,21 @@ bun run test:coverage:report

### GitHub Actions

This repository uses pre-configured GitHub Actions. The contracts are linted and tested on every push and pull requests. You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml).

This repository uses pre-configured GitHub Actions. The contracts are linted and tested on every push and pull requests.
You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml).

## Foundry Resources

This template builds upon the frameworks and libraries mentioned above, so please consult their respective documentation for details about their specific features.
This template builds upon the frameworks and libraries mentioned above, so please consult their respective documentation
for details about their specific features.

For example, if you're interested in exploring Foundry in more detail, you should look at the
[Foundry Book](https://book.getfoundry.sh/). In particular, you may be interested in reading the
[Writing Tests](https://book.getfoundry.sh/forge/writing-tests.html) tutorial.


[`HypERC20Collateral`]: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20Collateral.sol
[`HypERC20`]: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20.sol
[`Mailbox`]: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/Mailbox.sol
[`HypERC20Collateral`]:
https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20Collateral.sol
[`HypERC20`]:
https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20.sol
[`Mailbox`]:
https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/Mailbox.sol
74 changes: 44 additions & 30 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ graph TD
end
```

**scenario 2:** the token was migrated from LUKSO to Ethereum and an HypERC20 token contract was created as a wrapper on the Ethereum side (_e.g: wrapped Chillwhale or wrapped FABS as HypERC20_).
**scenario 2:** the token was migrated from LUKSO to Ethereum and an HypERC20 token contract was created as a wrapper on
the Ethereum side (_e.g: wrapped Chillwhale or wrapped FABS as HypERC20_).

The user burn the wrapped token `HypERC20` on Ethereum, and the tokens are unlocked on the LUKSO side and transferred to the user.
The user burns the wrapped token `HypERC20` on Ethereum, and the tokens are unlocked on the LUKSO side and transferred
to the user.

```mermaid
%% Ethereum -> LUKSO - LSP7 token that was initially bridged from LUKSO
Expand All @@ -45,7 +47,8 @@ graph TD

- **scenario 3:** the LSP7 token was originally created and deployed on LUKSO (_e.g: Chillwhale, FABS, etc..._).

The user transfer the LSP7 token to its `HypLSP7Collateral` contract on LUKSO where it is locked. The HypERC20 token on Ethereum is then minted for the user.
The user transfers the LSP7 token to its `HypLSP7Collateral` contract on LUKSO where it is locked. The HypERC20 token on
Ethereum is then minted for the user.

```mermaid
graph TD
Expand All @@ -61,7 +64,8 @@ graph TD
end
```

- **scenario 4:** an ERC20 token was bridged from Ethereum to LUKSO and we want to bridge back to Ethereum (_e.g: wrapped DAI as HypLSP7_).
- **scenario 4:** an ERC20 token was bridged from Ethereum to LUKSO and we want to bridge back to Ethereum (_e.g:
wrapped DAI as HypLSP7_).

This HypLSP7 token is burnt on LUKSO, on Ethereum it is unlocked.

Expand All @@ -79,80 +83,90 @@ graph TD
end
```


## Detailed Architecture Diagrams

> **Notes:** in the architecture diagram below:
>
> - The `Yaho` contracts handle the dispatching and batching of messages across chains.
> - The `Yaru` contracts ensures that the messages are properly executed on the destination chain by calling relevant functions like `onMessage`.
> - The `Yaru` contracts ensures that the messages are properly executed on the destination chain by calling relevant
> functions like `onMessage`. For more infos, see the
> [**Key Contracts**](https://crosschain-alliance.gitbook.io/hashi/api-and-smart-contracts/key-contracts) section on
> the Hashi Alliance docs.
### Ethereum -> LUKSO

> **Note:** This detailed diagram corresponds to the [**scenario 1**](#ethereum---lukso) above. Where an ERC20 token that initially exists on Ethereum (_e.g: DAI, USDC, etc..._) is bridged to LUKSO.
> **Note:** This detailed diagram corresponds to the [**scenario 1**](#ethereum---lukso) above. Where an ERC20 token
> that initially exists on Ethereum (_e.g: DAI, USDC, etc..._) is bridged to LUKSO.
![Ethereum to LUKSO bridge flow](../assets/flow-ethereum-lukso-hashi-bridge.png)


**on Ethereum chain**

1. User transfer ERC20 tokens to [`HypERC20Collateral`]. This locks the tokens in the collateral contract.
2. `HypERC20Collateral` contract call [`Mailbox`] to pass the message.
2. `HypERC20Collateral` contract calls [`Mailbox`] to pass the message via the `transferRemote(...)` function.
(Internally, the functions `__Router_dispatch(..) -> mailbox.dispatch(...)` are called to dispatch the message to the
mailbox).
3. The `Mailbox` calls:
- 3.1. the default Hook (created by Hyperlane),
- 3.2. and the Hashi Hook (created by CCIA team).
4. Hashi Hook dispatch the token relaying message from `Yaho` contracts.



**Off chain**

5. Hashi relayer (managed by CCIA team) listen for events from `Yaho` contracts and request the reporter contracts to relay token relaying message.
6. Hashi executor (managed by CCIA team) listen to event from each Hashi adapter contracts and call `Yaru.executeMessages`. **This step checks whether the Hashi adapters agree on a specify message id** (a threshold number of hash is stored), and set the message Id to verified status.
5. Hashi relayer (managed by CCIA team) listen for events from `Yaho` contracts and request the reporter contracts to
relay token relaying message.
6. Hashi executor (managed by CCIA team) listen to event from each Hashi adapter contracts and call
`Yaru.executeMessages`. **This step checks whether the Hashi adapters agree on a specify message id** (a threshold
number of hash is stored), and set the message Id to verified status.
7. Validator (run by Hyperlane & LUKSO team) will sign the Merkle root when new dispatches happen in Mailbox.
8. Hyperlane relayer (run by Hyperlane team) relays the message by calling Mailbox.process().
8. Hyperlane relayer (run by Hyperlane team) relays the message by calling `Mailbox.process(...)`.

**on LUKSO chain**

8. When [`Mailbox.process(...)`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/3d116132b87d36af9576d6b116f31a53d680db4a/solidity/contracts/Mailbox.sol#L188-L197) is called, it will:
- 8.1. check with Multisig ISM (includes Hashi ISM), whether the message is signed by validators & verified by Hashi ISM.
- 8.2. If so, it will mint [HypLSP7](./src/HypLSP7.sol) tokens to the receiver.
8. When
[`Mailbox.process(...)`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/3d116132b87d36af9576d6b116f31a53d680db4a/solidity/contracts/Mailbox.sol#L188-L197)
is called, it will:

- 8.1. check with Multisig ISM (includes Hashi ISM), whether the message is signed by validators & verified by Hashi
ISM.
- 8.2. If so, it will mint [HypLSP7](./src/HypLSP7.sol) tokens to the receiver.

### LUKSO -> Ethereum

> **Note:** This detailed diagram corresponds to the [**scenario 4**](#lukso---ethereum) above. Where an ERC20 token was bridged from Ethereum to LUKSO and we want to bridge back to Ethereum (_e.g: wrapped DAI as HypLSP7_).
> **Note:** This detailed diagram corresponds to the [**scenario 4**](#lukso---ethereum) above. Where an ERC20 token was
> bridged from Ethereum to LUKSO and we want to bridge back to Ethereum (_e.g: wrapped DAI as HypLSP7_).
![LUKSO to Ethereum bridge flow](../assets/flow-lukso-ethereum-hashi-bridge.png)

**on LUKSO chain**

> _Step 1 to 3 needs to be confirmed_
1. User transfer LSP7 token to HypLSP7 contract and the tokens are burnt.
1. User transfers LSP7 token to HypLSP7 contract and the tokens are burnt.
2. HypLSP7 contract calls `Mailbox` to pass the message.
3. `Mailbox` calls Default Hook (created by Hyperlane) and Hashi Hook (created by CCIA team).
4. Hashi Hook dispatch the token relaying message from Yaho contracts.
4. Hashi Hook dispatches the token relaying message from Yaho contracts.

**Off chain**

4. Off chain process remains the same as before, _except there is no Light Client support for Hashi from LUKSO → Ethereum_.
4. Off chain process remains the same as before, _except there is no Light Client support for Hashi from LUKSO →
Ethereum_.

**on Ethereum chain**

5. When `Mailbox.process()` is called:
- 5.1. it will check with Multisig ISM (includes Hashi ISM), whether the message is signed by validators & verified by Hashi ISM.
- 5.1. it will check with Multisig ISM (includes Hashi ISM), whether the message is signed by validators & verified
by Hashi ISM.
- 5.2. If so, it will unlock ERC20 token to the receiver on the Ethereum chain.






## Relevant links & resources

- [Cross Chain Alliance - Hashi](https://crosschain-alliance.gitbook.io/hashi)
- [Hyperlane smart contracts monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo)

[`HypERC20Collateral`]: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20Collateral.sol
[`HypERC20`]: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20.sol
[`Mailbox`]: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/Mailbox.sol
[`HypERC20Collateral`]:
https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20Collateral.sol
[`HypERC20`]:
https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/token/HypERC20.sol
[`Mailbox`]:
https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/%40hyperlane-xyz/core%405.2.0/solidity/contracts/Mailbox.sol
88 changes: 44 additions & 44 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config

[profile.default]
auto_detect_solc = false
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
evm_version = "shanghai"
fuzz = { runs = 1_000 }
gas_reports = ["*"]
optimizer = true
optimizer_runs = 10_000
out = "out"
script = "script"
solc = "0.8.25"
src = "src"
test = "test"
auto_detect_solc = false
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
evm_version = "shanghai"
fuzz = { runs = 1_000 }
gas_reports = ["*"]
optimizer = true
optimizer_runs = 10_000
out = "out"
script = "script"
solc = "0.8.25"
src = "src"
test = "test"

[profile.ci]
fuzz = { runs = 10_000 }
verbosity = 4
fuzz = { runs = 10_000 }
verbosity = 4

[etherscan]
arbitrum = { key = "${API_KEY_ARBISCAN}" }
avalanche = { key = "${API_KEY_SNOWTRACE}" }
base = { key = "${API_KEY_BASESCAN}" }
bnb_smart_chain = { key = "${API_KEY_BSCSCAN}" }
gnosis_chain = { key = "${API_KEY_GNOSISSCAN}" }
goerli = { key = "${API_KEY_ETHERSCAN}" }
mainnet = { key = "${API_KEY_ETHERSCAN}" }
optimism = { key = "${API_KEY_OPTIMISTIC_ETHERSCAN}" }
polygon = { key = "${API_KEY_POLYGONSCAN}" }
sepolia = { key = "${API_KEY_ETHERSCAN}" }
arbitrum = { key = "${API_KEY_ARBISCAN}" }
avalanche = { key = "${API_KEY_SNOWTRACE}" }
base = { key = "${API_KEY_BASESCAN}" }
bnb_smart_chain = { key = "${API_KEY_BSCSCAN}" }
gnosis_chain = { key = "${API_KEY_GNOSISSCAN}" }
goerli = { key = "${API_KEY_ETHERSCAN}" }
mainnet = { key = "${API_KEY_ETHERSCAN}" }
optimism = { key = "${API_KEY_OPTIMISTIC_ETHERSCAN}" }
polygon = { key = "${API_KEY_POLYGONSCAN}" }
sepolia = { key = "${API_KEY_ETHERSCAN}" }

[fmt]
bracket_spacing = true
int_types = "long"
line_length = 120
multiline_func_header = "all"
number_underscore = "thousands"
quote_style = "double"
tab_width = 4
wrap_comments = true
bracket_spacing = true
int_types = "long"
line_length = 120
multiline_func_header = "all"
number_underscore = "thousands"
quote_style = "double"
tab_width = 4
wrap_comments = true

[rpc_endpoints]
arbitrum = "https://arbitrum-mainnet.infura.io/v3/${API_KEY_INFURA}"
avalanche = "https://avalanche-mainnet.infura.io/v3/${API_KEY_INFURA}"
base = "https://mainnet.base.org"
bnb_smart_chain = "https://bsc-dataseed.binance.org"
gnosis_chain = "https://rpc.gnosischain.com"
goerli = "https://goerli.infura.io/v3/${API_KEY_INFURA}"
localhost = "http://localhost:8545"
mainnet = "https://eth-mainnet.g.alchemy.com/v2/${API_KEY_ALCHEMY}"
optimism = "https://optimism-mainnet.infura.io/v3/${API_KEY_INFURA}"
polygon = "https://polygon-mainnet.infura.io/v3/${API_KEY_INFURA}"
sepolia = "https://sepolia.infura.io/v3/${API_KEY_INFURA}"
arbitrum = "https://arbitrum-mainnet.infura.io/v3/${API_KEY_INFURA}"
avalanche = "https://avalanche-mainnet.infura.io/v3/${API_KEY_INFURA}"
base = "https://mainnet.base.org"
bnb_smart_chain = "https://bsc-dataseed.binance.org"
gnosis_chain = "https://rpc.gnosischain.com"
goerli = "https://goerli.infura.io/v3/${API_KEY_INFURA}"
localhost = "http://localhost:8545"
mainnet = "https://eth-mainnet.g.alchemy.com/v2/${API_KEY_ALCHEMY}"
optimism = "https://optimism-mainnet.infura.io/v3/${API_KEY_INFURA}"
polygon = "https://polygon-mainnet.infura.io/v3/${API_KEY_INFURA}"
sepolia = "https://sepolia.infura.io/v3/${API_KEY_INFURA}"
2 changes: 1 addition & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
@/=node_modules/@
forge-std/=node_modules/forge-std/
forge-std/=node_modules/forge-std
12 changes: 0 additions & 12 deletions script/Deploy.s.sol

This file was deleted.

Loading

0 comments on commit dd7d601

Please sign in to comment.