Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions .github/workflows/contracts-governance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
working-directory: contracts/governance
run: pnpm install --frozen-lockfile

- name: Run lint
working-directory: contracts/governance
run: pnpm run lint:js

- name: Run compile
working-directory: contracts/governance
run: pnpm run compile
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/contracts-safe-hardhat-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
working-directory: contracts/safe
run: npm ci

- name: Run lint
working-directory: contracts/safe
run: npm run prettier:check && npm run lint:sol

- name: Run unit tests
working-directory: contracts/safe
run: make test
4 changes: 4 additions & 0 deletions .github/workflows/contracts-solana-oft-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ jobs:
working-directory: contracts/solanaOFT
run: pnpm install --frozen-lockfile

- name: Run lint
working-directory: contracts/solanaOFT
run: pnpm run lint

- name: Run unit tests
working-directory: contracts/solanaOFT
run: pnpm run test:forge
4 changes: 4 additions & 0 deletions .github/workflows/contracts-token-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
working-directory: contracts/token
run: pnpm install --frozen-lockfile

- name: Run lint
working-directory: contracts/token
run: pnpm run lint

- name: Run compile
working-directory: contracts/token
run: pnpm run compile
Expand Down
17 changes: 12 additions & 5 deletions contracts/governance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,36 @@
1/ Fill the `.env` file (see `.env.example`), use a `PRIVATE_KEY` from an account funded on both chains.

2/ Deploy the `GovernanceOAppSender` contract by running:

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

And select `ethereum-testnet` network then enter the `GovernanceOAppSender` script.

3/ Deploy the `GovernanceOAppReceiver` contract by running:

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

And select `gateway-testnet` network then enter the `GovernanceOAppReceiver` script.

4/ Wire contracts:

```bash
npx hardhat lz:oapp:wire --oapp-config layerzero.config.testnet.ts
```

5/ After the Safe and AdminModule have been deployed, run:
5/ After the Safe and AdminModule have been deployed, run:

```bash
npx hardhat task:setAdminSafeModule --module <ADMIN_MODULE_ADDRESS> --network gateway-testnet
```

6/ Verify contracts:
6/ Verify contracts:

```bash
pnpm verify:etherscan:ethereum:testnet
pnpm verify:etherscan:gateway:testnet
```
```
3 changes: 2 additions & 1 deletion contracts/governance/tasks/getLZOptions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Options } from '@layerzerolabs/lz-v2-utilities'
import { task, types } from 'hardhat/config'

import { Options } from '@layerzerolabs/lz-v2-utilities'

// eg use: `npx hardhat task:getLZOptions --gas-limit 300000`
task('task:getLZOptions')
.addParam('gasLimit', 'Gas limit for the LZ receive option', undefined, types.int)
Expand Down
3 changes: 2 additions & 1 deletion contracts/governance/tasks/getSafeOwnerChangeArgs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Options } from '@layerzerolabs/lz-v2-utilities'
import { task, types } from 'hardhat/config'
import { HardhatRuntimeEnvironment } from 'hardhat/types'

import { Options } from '@layerzerolabs/lz-v2-utilities'

// The SENTINEL_OWNERS is the head of the linked list in Safe's owner management
const SENTINEL_OWNERS = '0x0000000000000000000000000000000000000001'

Expand Down
3 changes: 2 additions & 1 deletion contracts/governance/tasks/setAdminSafeModule.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { task, types } from 'hardhat/config'
import { HardhatRuntimeEnvironment } from 'hardhat/types'

import { createLogger } from '@layerzerolabs/io-devtools'
const logger = createLogger()

task('task:setAdminSafeModule', 'Sets GovernanceOAppReceiver.adminSafeModule')
.addParam('module', 'AdminModule address to authorize', undefined, types.string)
.addOptionalParam('receiver', 'GovernanceOAppReceiver address (defaults to deployment)', undefined, types.string)
.setAction(async ({ module, receiver }: { module: string, receiver: string }, hre: HardhatRuntimeEnvironment) => {
.setAction(async ({ module, receiver }: { module: string; receiver: string }, hre: HardhatRuntimeEnvironment) => {
const { deployments, ethers, getNamedAccounts } = hre

const moduleAddress = ethers.utils.getAddress(module)
Expand Down
5 changes: 3 additions & 2 deletions contracts/governance/test/GovernanceOApp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import { expect } from 'chai'
import { Contract, ContractFactory } from 'ethers'
import { deployments, ethers } from 'hardhat'
import { execTransaction } from './utils/execTransaction'

import { Options } from '@layerzerolabs/lz-v2-utilities'
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { Options } from '@layerzerolabs/lz-v2-utilities'

import { execTransaction } from './utils/execTransaction'

describe('GovernanceOApp Test', function () {
const eidA = EndpointId.SEPOLIA_V2_TESTNET
Expand Down Expand Up @@ -270,7 +271,7 @@
try {
await tx
expect.fail('withdrawETH should have reverted with InvalidNullRecipient')
} catch (err: any) {

Check warning on line 274 in contracts/governance/test/GovernanceOApp.test.ts

View workflow job for this annotation

GitHub Actions / contracts-governance-tests/tests (bpr)

Unexpected any. Specify a different type
const data = err.data
const selector = data.slice(0, 10)
const expected = governanceOAppSender.interface.getSighash('InvalidNullRecipient()')
Expand Down Expand Up @@ -313,7 +314,7 @@
try {
await tx
expect.fail('withdrawETH should have reverted with InvalidNullRecipient')
} catch (err: any) {

Check warning on line 317 in contracts/governance/test/GovernanceOApp.test.ts

View workflow job for this annotation

GitHub Actions / contracts-governance-tests/tests (bpr)

Unexpected any. Specify a different type
const data = err.data
const selector = data.slice(0, 10)
const expected = governanceOAppReceiver.interface.getSighash('InvalidNullRecipient()')
Expand Down
2 changes: 1 addition & 1 deletion contracts/governance/test/utils/execTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Contract, Signer } from 'ethers'
import { ethers } from 'hardhat'
import { Signer, Contract } from 'ethers'

/**
* Executes a transaction on the Safe contract.
Expand Down
3 changes: 3 additions & 0 deletions contracts/safe/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"rules": {}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[AUTOMATED] Nit: The empty "rules": {} solhint config is fine as a placeholder to unblock lint:sol in CI. Consider adding a TODO comment or tracking issue to populate actual rules later, so this doesn't get forgotten.

Confidence: 85/100

}
3 changes: 3 additions & 0 deletions contracts/safe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
## Deploy Multisig Safe Wallet with only the deployer as owner

Be sure to start with an `.env` - or copy paste the `.env.example.deploy` and fill its values (not to be confused with `.env.example.test` to be used to run tests in hardhat only!) - with just those filled variables:

```
PRIVATE_KEY=
RPC_URL_ZAMA_GATEWAY_TESTNET=
```

Then run:

```
npx hardhat compile
npx hardhat task:deploySafe --network gateway-testnet
Expand All @@ -17,6 +19,7 @@ npx hardhat task:deploySafe --network gateway-testnet
This will deploy `SafeL2` singleton contract, as well as `SafeProxyFactory` and `SafeL2Proxy`. The `SafeL2Proxy` is actually the multisig wallet which will become later the owner of `GatewayConfig`.

Then, after waiting for around 1 minute for the blockscout indexing to take into consideration newly deployed contracts, run:

```
npx hardhat task:verifySafe --network gateway-testnet
```
Expand Down
37 changes: 26 additions & 11 deletions contracts/safe/tasks/acceptOwnership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@ task(
"task:acceptOwnership",
`Accepts ownership of a contract from the Safe Smart Account.`,
)
.addParam("address", "Address of the contract to accept ownership of.", undefined, types.string)
.addParam(
"address",
"Address of the contract to accept ownership of.",
undefined,
types.string,
)
.setAction(async function ({ address }, { ethers }) {
const ownerPrivateKeysEnv = process.env[SAFE_OWNER_PRIVATE_KEYS_ENV];
if (!ownerPrivateKeysEnv) {
throw new Error(`"${SAFE_OWNER_PRIVATE_KEYS_ENV}" env variable is not set`);
throw new Error(
`"${SAFE_OWNER_PRIVATE_KEYS_ENV}" env variable is not set`,
);
}
const signers = JSON.parse(ownerPrivateKeysEnv).map((ownerPrivateKey: string) =>
new Wallet(ownerPrivateKey).connect(ethers.provider),
const signers = JSON.parse(ownerPrivateKeysEnv).map(
(ownerPrivateKey: string) =>
new Wallet(ownerPrivateKey).connect(ethers.provider),
);

const acceptOwnershipAbi = [
"function acceptOwnership() public",
];
const contractToCall = await ethers.getContractAt(acceptOwnershipAbi, address);
const { safeProxy: safe, safeProxyAddress } = await getSafeProxyAddress(ethers);
const acceptOwnershipAbi = ["function acceptOwnership() public"];
const contractToCall = await ethers.getContractAt(
acceptOwnershipAbi,
address,
);
const { safeProxy: safe, safeProxyAddress } =
await getSafeProxyAddress(ethers);

const value = 0;
const data = contractToCall.interface.encodeFunctionData("acceptOwnership");
Expand Down Expand Up @@ -68,12 +78,17 @@ task(
);
});

async function getSortedSignatures(signers: Wallet[], transactionHash: string): Promise<string> {
async function getSortedSignatures(
signers: Wallet[],
transactionHash: string,
): Promise<string> {
const bytesDataHash = getBytes(transactionHash);

let signatureBytes = "0x";

const signerAddresses = await Promise.all(signers.map((signer) => signer.getAddress()));
const signerAddresses = await Promise.all(
signers.map((signer) => signer.getAddress()),
);

const sortedSigners = signers.sort((a, b) => {
const addressA = signerAddresses[signers.indexOf(a)];
Expand Down
3 changes: 2 additions & 1 deletion contracts/solanaOFT/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ out
*.sol
*.yaml
*.lock
package-lock.json
package-lock.json
deployments/
3 changes: 2 additions & 1 deletion contracts/solanaOFT/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ out/
*.yaml
*.lock
package-lock.json
package.json
package.json
deployments/
6 changes: 3 additions & 3 deletions contracts/solanaOFT/ADD_SOLANA_OFT_TESTNET.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ First make sure you have installed all needed dependencies via `pnpm i` and fill

### Prepare the Solana OFT Program keypair

Run `anchor keys sync -p oft` command. This will create the OFT `programId` keypair and also automatically update `Anchor.toml` to use the generated keypair's public key. The default path for the program's keypair will be `target/deploy/oft-keypair.json`. The program keypair is only used for initial deployment of the program.
Run `anchor keys sync -p oft` command. This will create the OFT `programId` keypair and also automatically update `Anchor.toml` to use the generated keypair's public key. The default path for the program's keypair will be `target/deploy/oft-keypair.json`. The program keypair is only used for initial deployment of the program.

__Optional:__ you can use `anchor keys list` to view the program ID's based on the generated keypairs.
**Optional:** you can use `anchor keys list` to view the program ID's based on the generated keypairs.

Copy the `oft` program ID value for use in the build step later.

Expand Down Expand Up @@ -112,4 +112,4 @@ Upon a successful send, the script will provide you with the link to the message

Once the message is delivered, you will be able to click on the destination transaction hash to verify that the OFT was sent.

Congratulations, you have now sent an OFT between Solana and Ethereum!
Congratulations, you have now sent an OFT between Solana and Ethereum!
16 changes: 8 additions & 8 deletions contracts/solanaOFT/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ The goal of this runbook is to guide you step by step on how to deploy a ZAMA OF

## Step 1 : Deploy the OFT on Solana Chain

First make sure you have installed all needed dependencies via `pnpm i` and filled the `.env` file correctly: see [`.env.example`](./.env.example) file. Default recommendation is to fill only those 3 values: `PRIVATE_KEY`, `RPC_URL_ETHEREUM` and `RPC_URL_SOLANA` values, as this will use the default Solana config and local keypair, which should be setup first via `solana config set --url mainnet-beta` and the local keypair generated with `solana-keygen` command.
First make sure you have installed all needed dependencies via `pnpm i` and filled the `.env` file correctly: see [`.env.example`](./.env.example) file. Default recommendation is to fill only those 3 values: `PRIVATE_KEY`, `RPC_URL_ETHEREUM` and `RPC_URL_SOLANA` values, as this will use the default Solana config and local keypair, which should be setup first via `solana config set --url mainnet-beta` and the local keypair generated with `solana-keygen` command.

For the `RPC_URL_SOLANA` value, we recommend getting one from [Helius](https://www.helius.dev/).

Please make sure to fund your public key with 5 SOL on Solana mainnet, before deploying.

### Prepare the Solana OFT Program keypair

Run `anchor keys sync -p oft` command. This will create the OFT `programId` keypair and also automatically update `Anchor.toml` to use the generated keypair's public key. The default path for the program's keypair will be `target/deploy/oft-keypair.json`. The program keypair is only used for initial deployment of the program.
Run `anchor keys sync -p oft` command. This will create the OFT `programId` keypair and also automatically update `Anchor.toml` to use the generated keypair's public key. The default path for the program's keypair will be `target/deploy/oft-keypair.json`. The program keypair is only used for initial deployment of the program.

__Optional:__ you can use `anchor keys list` to view the program ID's based on the generated keypairs.
**Optional:** you can use `anchor keys list` to view the program ID's based on the generated keypairs.

Copy the `oft` program ID value for use in the build step later.

Expand Down Expand Up @@ -98,7 +98,7 @@ After voting and execution of the wiring proposal, your OFT is now successfully

## Step 4 : Test OFT transfers

First, make sure the Solidity contracts are compiled by running `npx hardhat compile`.
First, make sure the Solidity contracts are compiled by running `npx hardhat compile`.

Send 1 OFT from **Ethereum** to **Solana**:

Expand Down Expand Up @@ -149,7 +149,7 @@ The transfer of both require modifying your LZ Config file and running helper ta

Overall, you should carry out these steps:

1/ Modify `layerzero.config.ts` to include **only** the new delegate address. This means that the exported function at the end of the config file should be as:
1/ Modify `layerzero.config.ts` to include **only** the new delegate address. This means that the exported function at the end of the config file should be as:

```
export default async function () {
Expand Down Expand Up @@ -184,7 +184,7 @@ Notice from this snippet that only the returned value changed, and that `<SQUADS

2/ Run `pnpm hardhat lz:oapp:wire --oapp-config layerzero.config.ts`.

3/ Modify `layerzero.config.ts` to include the new owner address. This means that the exported function at the end of the config file should be now as:
3/ Modify `layerzero.config.ts` to include the new owner address. This means that the exported function at the end of the config file should be now as:

```
export default async function () {
Expand Down Expand Up @@ -231,7 +231,7 @@ solana program set-upgrade-authority --skip-new-upgrade-authority-signer-check <
New upgrade authority can be easily checked via any Solana block explorer.

### Transfer token metadata update authority

Use this command by replacing `<MINT_ADDRESS>` by its actual value, which could be read from `deployments/solana-mainnet/OFT.json`:

```
Expand Down Expand Up @@ -295,4 +295,4 @@ Finally run:

```
solana-verify remote submit-job --program-id <OFT_PROGRAM_ID> --uploader <SQUADS_VAULT_ID> --url mainnet
```
```
4 changes: 0 additions & 4 deletions contracts/solanaOFT/docs/wiring-to-aptos.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ Currently, you can only perform **one-way wiring from Solana → Move-VM** using
#### Deployment Process

1. **Create and Deploy Solana Example**

- Create the Solana example: `LZ_ENABLE_SOLANA_OAPP_EXAMPLE=1 npx create-lz-oapp@latest`
- Deploy to Solana following the deployment instructions in the Solana example README

2. **Create and Deploy Aptos Move Example**

- Create the Aptos Move example: `LZ_ENABLE_EXPERIMENTAL_MOVE_VM_EXAMPLES=1 npx create-lz-oapp@latest`
- Deploy to Aptos following the deployment and initialization instructions in the Aptos example README

Expand All @@ -32,7 +30,6 @@ Currently, you can only perform **one-way wiring from Solana → Move-VM** using
```

3. **Configure Solana Example**

- Navigate to the Solana example directory
- Use the example configuration at `./docs/move.layerzero.config.ts`
- Fill out the configuration with your desired values
Expand All @@ -53,7 +50,6 @@ Currently, you can only perform **one-way wiring from Solana → Move-VM** using
If these commands succeed, you have successfully wired the Solana contract to the Aptos Move contract.

5. **Wire Aptos to Solana**

- Transfer the `move.layerzero.config.ts` file from the Solana example to the Aptos Move example directory
- In the Aptos Move example directory, run:
```bash
Expand Down
1 change: 1 addition & 0 deletions contracts/solanaOFT/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"@solana/web3.js": "^1.98.0",
"ethers": "^5.7.2",
"hardhat-deploy": "^0.12.1",
"@eslint/eslintrc>ajv": "^6.12.4",
"ajv@<6.14.0": ">=6.14.0 <7.0.0",
"ajv@>=7.0.0-alpha.0 <8.18.0": ">=8.18.0 <9.0.0",
"axios@<0.31.0": ">=0.31.0",
Expand Down
Loading
Loading