Skip to content

Commit

Permalink
🗞️ Adding in OFTAdapter to create-lz-oapp (#713)
Browse files Browse the repository at this point in the history
  • Loading branch information
sirarthurmoney authored Jul 19, 2024
1 parent 6c3ec22 commit 3e88d26
Show file tree
Hide file tree
Showing 32 changed files with 1,580 additions and 65 deletions.
6 changes: 6 additions & 0 deletions .changeset/forty-monkeys-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"create-lz-oapp": patch
"@layerzerolabs/oft-adapter-example": patch
---

Adding in OFTAdapter to create-lz-oapp
15 changes: 15 additions & 0 deletions examples/oft-adapter/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
#
# Example environment configuration
#
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'

# By default, the examples support both mnemonic-based and private key-based authentication
#
# You don't need to set both of these values, just pick the one that you prefer and set that one
MNEMONIC=
PRIVATE_KEY=
10 changes: 10 additions & 0 deletions examples/oft-adapter/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
artifacts
cache
dist
node_modules
out
*.log
*.sol
*.yaml
*.lock
package-lock.json
10 changes: 10 additions & 0 deletions examples/oft-adapter/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require('@rushstack/eslint-patch/modern-module-resolution');

module.exports = {
extends: ['@layerzerolabs/eslint-config-next/recommended'],
rules: {
// @layerzerolabs/eslint-config-next defines rules for turborepo-based projects
// that are not relevant for this particular project
'turbo/no-undeclared-env-vars': 'off',
},
};
24 changes: 24 additions & 0 deletions examples/oft-adapter/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
node_modules
.env
coverage
coverage.json
typechain
typechain-types

# Hardhat files
cache
artifacts


# LayerZero specific files
.layerzero

# foundry test compilation files
out

# pnpm
pnpm-error.log

# Editor and OS files
.DS_Store
.idea
1 change: 1 addition & 0 deletions examples/oft-adapter/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.18.0
10 changes: 10 additions & 0 deletions examples/oft-adapter/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
artifacts/
cache/
dist/
node_modules/
out/
*.log
*ignore
*.yaml
*.lock
package-lock.json
3 changes: 3 additions & 0 deletions examples/oft-adapter/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
...require('@layerzerolabs/prettier-config-next'),
};
120 changes: 120 additions & 0 deletions examples/oft-adapter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<p align="center">
<a href="https://layerzero.network">
<img alt="LayerZero" style="width: 400px" src="https://docs.layerzero.network/img/LayerZero_Logo_White.svg"/>
</a>
</p>

<p align="center">
<a href="https://layerzero.network" style="color: #a77dff">Homepage</a> | <a href="https://docs.layerzero.network/" style="color: #a77dff">Docs</a> | <a href="https://layerzero.network/developers" style="color: #a77dff">Developers</a>
</p>

<h1 align="center">OFTAdapter Example</h1>

<p align="center">
<a href="https://docs.layerzero.network/v2/developers/evm/oft/adapter" style="color: #a77dff">Quickstart</a> | <a href="https://docs.layerzero.network/contracts/oapp-configuration" style="color: #a77dff">Configuration</a> | <a href="https://docs.layerzero.network/contracts/options" style="color: #a77dff">Message Execution Options</a> | <a href="https://docs.layerzero.network/contracts/endpoint-addresses" style="color: #a77dff">Endpoint Addresses</a>
</p>

<p align="center">Template project for getting started with LayerZero's <code>OFTAdapter</code> contract development.</p>

### OFTAdapter additional setup:

- In your `hardhat.config.ts` file, add the following configuration to the network you want to deploy the OFTAdapter to:
```typescript
// Replace `0x0` with the address of the ERC20 token you want to adapt to the OFT functionality.
oftAdapter: {
tokenAddress: '0x0',
}
```

## 1) Developing Contracts

#### Installing dependencies

We recommend using `pnpm` as a package manager (but you can of course use a package manager of your choice):

```bash
pnpm install
```

#### Compiling your contracts

This project supports both `hardhat` and `forge` compilation. By default, the `compile` command will execute both:

```bash
pnpm compile
```

If you prefer one over the other, you can use the tooling-specific commands:

```bash
pnpm compile:forge
pnpm compile:hardhat
```

Or adjust the `package.json` to for example remove `forge` build:

```diff
- "compile": "$npm_execpath run compile:forge && $npm_execpath run compile:hardhat",
- "compile:forge": "forge build",
- "compile:hardhat": "hardhat compile",
+ "compile": "hardhat compile"
```

#### Running tests

Similarly to the contract compilation, we support both `hardhat` and `forge` tests. By default, the `test` command will execute both:

```bash
pnpm test
```

If you prefer one over the other, you can use the tooling-specific commands:

```bash
pnpm test:forge
pnpm test:hardhat
```

Or adjust the `package.json` to for example remove `hardhat` tests:

```diff
- "test": "$npm_execpath test:forge && $npm_execpath test:hardhat",
- "test:forge": "forge test",
- "test:hardhat": "$npm_execpath hardhat test"
+ "test": "forge test"
```

## 2) Deploying Contracts

Set up deployer wallet/account:

- Rename `.env.example` -> `.env`
- Choose your preferred means of setting up your deployer wallet/account:

```
MNEMONIC="test test test test test test test test test test test junk"
or...
PRIVATE_KEY="0xabc...def"
```

- Fund this address with the corresponding chain's native tokens you want to deploy to.

To deploy your contracts to your desired blockchains, run the following command in your project's folder:

```bash
npx hardhat lz:deploy
```

More information about available CLI arguments can be found using the `--help` flag:

```bash
npx hardhat lz:deploy --help
```

By following these steps, you can focus more on creating innovative omnichain solutions and less on the complexities of cross-chain communication.

<br></br>

<p align="center">
Join our community on <a href="https://discord-layerzero.netlify.app/discord" style="color: #a77dff">Discord</a> | Follow us on <a href="https://twitter.com/LayerZero_Labs" style="color: #a77dff">Twitter</a>
</p>
14 changes: 14 additions & 0 deletions examples/oft-adapter/contracts/MyOFT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol";

contract MyOFT is OFT {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate
) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {}
}
24 changes: 24 additions & 0 deletions examples/oft-adapter/contracts/MyOFTAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OFTAdapter } from "@layerzerolabs/oft-evm/contracts/OFTAdapter.sol";

/**
* @title OFTAdapter Contract
* @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
*
* @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
* @dev WARNING: ONLY 1 of these should exist for a given global mesh,
* unless you make a NON-default implementation of OFT and needs to be done very carefully.
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
*/
contract MyOFTAdapter is OFTAdapter {
constructor(
address _token,
address _lzEndpoint,
address _delegate
) OFTAdapter(_token, _lzEndpoint, _delegate) Ownable(_delegate) {}
}
13 changes: 13 additions & 0 deletions examples/oft-adapter/contracts/mocks/MyERC20Mock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

// @dev WARNING: This is for testing purposes only
contract MyERC20Mock is ERC20 {
constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}

function mint(address _to, uint256 _amount) public {
_mint(_to, _amount);
}
}
9 changes: 9 additions & 0 deletions examples/oft-adapter/contracts/mocks/MyOFTAdapterMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import { MyOFTAdapter } from "../MyOFTAdapter.sol";

// @dev WARNING: This is for testing purposes only
contract MyOFTAdapterMock is MyOFTAdapter {
constructor(address _token, address _lzEndpoint, address _delegate) MyOFTAdapter(_token, _lzEndpoint, _delegate) {}
}
19 changes: 19 additions & 0 deletions examples/oft-adapter/contracts/mocks/MyOFTMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol";

// @dev WARNING: This is for testing purposes only
contract MyOFTMock is OFT {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate
) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {}

function mint(address _to, uint256 _amount) public {
_mint(_to, _amount);
}
}
60 changes: 60 additions & 0 deletions examples/oft-adapter/deploy/MyOFT.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import assert from 'assert'

import { type DeployFunction } from 'hardhat-deploy/types'

const contractName = 'MyOFT'

const deploy: DeployFunction = async (hre) => {
const { getNamedAccounts, deployments } = hre

const { deploy } = deployments
const { deployer } = await getNamedAccounts()

assert(deployer, 'Missing named deployer account')

console.log(`Network: ${hre.network.name}`)
console.log(`Deployer: ${deployer}`)

// This is an external deployment pulled in from @layerzerolabs/lz-evm-sdk-v2
//
// @layerzerolabs/toolbox-hardhat takes care of plugging in the external deployments
// from @layerzerolabs packages based on the configuration in your hardhat config
//
// For this to work correctly, your network config must define an eid property
// set to `EndpointId` as defined in @layerzerolabs/lz-definitions
//
// For example:
//
// networks: {
// fuji: {
// ...
// eid: EndpointId.AVALANCHE_V2_TESTNET
// }
// }
const endpointV2Deployment = await hre.deployments.get('EndpointV2')

// If the oftAdapter configuration is defined on a network that is deploying an OFT,
// the deployment will log a warning and skip the deployment
if (hre.network.config.oftAdapter != null) {
console.warn(`oftAdapter configuration found on OFT deployment, skipping OFT deployment`)
return
}

const { address } = await deploy(contractName, {
from: deployer,
args: [
'MyOFT', // name
'MOFT', // symbol
endpointV2Deployment.address, // LayerZero's EndpointV2 address
deployer, // owner
],
log: true,
skipIfAlreadyDeployed: false,
})

console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${address}`)
}

deploy.tags = [contractName]

export default deploy
Loading

0 comments on commit 3e88d26

Please sign in to comment.