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

CircleRelayer fix: not passing msg.value to integration. Moving from Goerli to Sepolia #43

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ Before deploying the contracts, set the `Deployment Variables` and `RPC` for you
Then deploy the contracts by executing the following commands:

```bash
# goerli
# sepolia
. env/testnet/eth.env && shell-scripts/deploy_circle_relayer.sh --private-key put_your_private_key_here

# fuji
@@ -71,11 +71,11 @@ You might need to specify all three of the following arguments:
So for example, you would execute:

```bash
# goerli
# sepolia
source env/testnet/eth.env && shell-scripts/deploy_circle_relayer.sh --ledger --mnemonic-derivation-paths your_derivation_path --sender your_address_for_given_path
```

to deploy on goerli with a ledger wallet.
to deploy on sepolia with a ledger wallet.

## Contract verification

25 changes: 12 additions & 13 deletions evm/env/testing.env
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
###############################################################################
#
# Ethereum Testnet (Goerli)
# Ethereum Testnet (Sepolia)
#
###############################################################################
export ETH_FORK_RPC=
export ETH_FORK_CHAIN_ID=5
export ETH_FORK_BLOCK_NUMBER=7892593
export ETH_USDC_TOKEN_ADDRESS=0x07865c6E87B9F70255377e024ace6630C1Eaa37F
export ETH_CIRCLE_BRIDGE_ADDRESS=0xdAbec94B97F7b5FCA28f050cC8EeAc2Dc9920476
export ETH_WORMHOLE_ADDRESS=0x706abc4E45D419950511e474C7B9Ed348A4a716c
export ETH_CIRCLE_INTEGRATION_ADDRESS=0x0a69146716b3a21622287efa1607424c663069a4
export ETH_CIRCLE_BRIDGE_ADDRESS=0xd0c3da58f55358142b8d3e06c1c30c5c6114efe8
export ETH_CIRCLE_TRANSMITTER_ADDRESS=0x26413e8157cd32011e726065a5462e97dd4d03d9
export ETH_FORK_RPC=https://sepolia.drpc.org
export ETH_FORK_CHAIN_ID=11155111
export ETH_FORK_BLOCK_NUMBER=7873216
export ETH_USDC_TOKEN_ADDRESS=0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238
export ETH_WORMHOLE_ADDRESS=0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78
export ETH_CIRCLE_INTEGRATION_ADDRESS=0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c
export ETH_CIRCLE_BRIDGE_ADDRESS=0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5
export ETH_CIRCLE_TRANSMITTER_ADDRESS=0x7865fAfC2db2093669d92c0F33AeEF291086BEFD
export ETH_SWAP_RATE_PRECISION=100000000
export WETH_ADDRESS=0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6
export WETH_ADDRESS=0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14
export ETH_NATIVE_TOKEN_DECIMALS=18

###############################################################################
@@ -43,7 +42,7 @@ export TESTING_WORMHOLE_ADDRESS=${ETH_WORMHOLE_ADDRESS}
export TESTING_FORK_RPC=${ETH_FORK_RPC}
export TESTING_FORK_CHAIN_ID=${ETH_FORK_CHAIN_ID}
export TESTING_WORMHOLE_CHAIN_ID=2
export TESTING_NATIVE_TOKEN_DECIMALS=${AVAX_NATIVE_TOKEN_DECIMALS}
export TESTING_NATIVE_TOKEN_DECIMALS=${ETH_NATIVE_TOKEN_DECIMALS}
export TESTING_WORMHOLE_MESSAGE_FEE=0
export TESTING_WORMHOLE_GUARDIAN_SET_INDEX=0
export TESTING_USDC_TOKEN_ADDRESS=${ETH_USDC_TOKEN_ADDRESS}
@@ -54,7 +53,7 @@ export TESTING_CIRCLE_BRIDGE_ADDRESS=${ETH_CIRCLE_BRIDGE_ADDRESS}
export TESTING_TARGET_CIRCLE_BRIDGE_ADDRESS=${AVAX_CIRCLE_BRIDGE_ADDRESS}
export TESTING_CIRCLE_TRANSMITTER_ADDRESS=${ETH_CIRCLE_TRANSMITTER_ADDRESS}

# Goerli wallets
# Sepolia wallets
export TESTING_RELAYER_WALLET=0x19Fde9295A2D01081364293C5BbF327B941C9C44
export TESTING_RECIPIENT_WALLET=0xEB15d7699592E1d8Ddab0073499B17C515AD0630
export TESTING_FEE_RECIPIENT=0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b
4 changes: 2 additions & 2 deletions evm/modules/src/CircleSimulator.sol
Original file line number Diff line number Diff line change
@@ -42,9 +42,9 @@ contract CircleSimulator {
"total supply overflow"
);
vm.startPrank(usdc.masterMinter());
usdc.configureMinter(msg.sender, type(uint256).max);
usdc.mint(msg.sender, amount);
usdc.configureMinter(address(this), type(uint256).max);
vm.stopPrank();
usdc.mint(msg.sender, amount);
}

/**
2 changes: 1 addition & 1 deletion evm/shell-scripts/make_ethers_types.sh
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@
SRC=$(dirname $0)/../out
DST=$(dirname $0)/../ts/src/ethers-contracts

typechain --target=ethers-v5 --out-dir=$DST $SRC/*/*.json
typechain --target=ethers-v5 --out-dir=$DST $SRC/*.sol/*.json
6 changes: 3 additions & 3 deletions evm/shell-scripts/run_integration_tests.sh
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ fi

echo "Starting anvil"

# ethereum goerli testnet
# ethereum sepolia testnet
anvil \
-m "myth like bonus scare over problem client lizard pioneer submit female collect" \
--port 8546 \
@@ -38,7 +38,7 @@ RELEASE_NATIVE_TOKEN_DECIMALS=$ETH_NATIVE_TOKEN_DECIMALS \
RELEASE_FEE_RECIPIENT=$TESTING_FEE_RECIPIENT \
RELEASE_OWNER_ASSISTANT=$TESTING_OWNER_ASSISTANT \
forge script forge-scripts/deploy_contracts.sol \
--rpc-url http://localhost:8546 \
--rpc-url http://127.0.0.1:8546 \
--private-key $PRIVATE_KEY \
--broadcast --slow > deploy.out 2>&1

@@ -48,7 +48,7 @@ RELEASE_NATIVE_TOKEN_DECIMALS=$AVAX_NATIVE_TOKEN_DECIMALS \
RELEASE_FEE_RECIPIENT=$TESTING_FEE_RECIPIENT \
RELEASE_OWNER_ASSISTANT=$TESTING_OWNER_ASSISTANT \
forge script forge-scripts/deploy_contracts.sol \
--rpc-url http://localhost:8547 \
--rpc-url http://127.0.0.1:8547 \
--private-key $PRIVATE_KEY \
--broadcast --slow >> deploy.out 2>&1

2 changes: 1 addition & 1 deletion evm/src/circle-relayer/CircleRelayer.sol
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ contract CircleRelayer is CircleRelayerMessages, CircleRelayerGovernance, Reentr
);

// transfer the tokens with instructions via the circle integration contract
messageSequence = integration.transferTokensWithPayload(
messageSequence = integration.transferTokensWithPayload{ value: msg.value }(
ICircleIntegration.TransferParameters({
token: address(token),
amount: amount,
9 changes: 4 additions & 5 deletions evm/ts/test/00_environment.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import {expect} from "chai";
import {ethers} from "ethers";
import {
CHAIN_ID_AVAX,
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
tryNativeToHexString,
} from "@certusone/wormhole-sdk";
import {
@@ -38,7 +38,7 @@ describe("Environment Test", () => {
});
});

describe("Ethereum Goerli Testnet Fork", () => {
describe("Ethereum Sepolia Testnet Fork", () => {
describe("Environment", () => {
it("Variables", () => {
expect(ETH_LOCALHOST).is.not.undefined;
@@ -67,7 +67,7 @@ describe("Environment Test", () => {

it("Wormhole", async () => {
const chainId = await wormhole.chainId();
expect(chainId).to.equal(CHAIN_ID_ETH as number);
expect(chainId).to.equal(CHAIN_ID_SEPOLIA as number);

// fetch current wormhole protocol fee
const messageFee: ethers.BigNumber = await wormhole.messageFee();
@@ -239,7 +239,7 @@ describe("Environment Test", () => {

// start prank (impersonate the Circle masterMinter)
await provider.send("anvil_impersonateAccount", [masterMinter]);

await provider.send("anvil_setBalance", [masterMinter, ethers.utils.parseEther("100").toString()]);
// configure my wallet as minter
{
const usdc = IUSDC__factory.connect(
@@ -260,7 +260,6 @@ describe("Environment Test", () => {

// stop prank
await provider.send("anvil_stopImpersonatingAccount", [masterMinter]);

// mint USDC and confirm with a balance check
{
const usdc = IUSDC__factory.connect(ETH_USDC_TOKEN_ADDRESS, wallet);
76 changes: 63 additions & 13 deletions evm/ts/test/01_circle_relayer.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import {expect} from "chai";
import {ethers} from "ethers";
import {
CHAIN_ID_AVAX,
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
tryNativeToHexString,
} from "@certusone/wormhole-sdk";
import {
@@ -28,6 +28,7 @@ import {
ICircleIntegration__factory,
IUSDC__factory,
IWormhole__factory,
IMessageTransmitter__factory,
} from "../src/ethers-contracts";
import {MockGuardians} from "@certusone/wormhole-sdk/lib/cjs/mock";
import {RedeemParameters} from "../src";
@@ -122,7 +123,7 @@ describe("Circle Integration Test", () => {
const avaxMaxNativeSwapAmount = ethers.utils.parseEther("100");

describe("Contract Setup", () => {
describe("Ethereum Goerli Testnet", () => {
describe("Ethereum Sepolia Testnet", () => {
it("Should Register Circle Relayer Target Contract", async () => {
// Convert the target contract address to bytes32, since other
// non-evm blockchains (e.g. Solana) have 32 byte wallet addresses.
@@ -178,7 +179,7 @@ describe("Circle Integration Test", () => {
// set the relayer fee for USDC
const receipt = await ethCircleRelayer
.connect(ethOwnerAssistantWallet)
.updateNativeSwapRate(CHAIN_ID_ETH, ethUsdc.address, nativeSwapRate)
.updateNativeSwapRate(CHAIN_ID_SEPOLIA, ethUsdc.address, nativeSwapRate)
.then((tx: ethers.ContractTransaction) => tx.wait())
.catch((msg: any) => {
// should not happen
@@ -198,7 +199,7 @@ describe("Circle Integration Test", () => {
// set the max native swap amount for USDC
const receipt = await ethCircleRelayer
.updateMaxNativeSwapAmount(
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
ethUsdc.address,
ethMaxNativeSwapAmount
)
@@ -224,11 +225,11 @@ describe("Circle Integration Test", () => {
// Convert the target contract address to bytes32, since other
// non-evm blockchains (e.g. Solana) have 32 byte wallet addresses.
const targetContractAddressHex =
"0x" + tryNativeToHexString(ethCircleRelayer.address, CHAIN_ID_ETH);
"0x" + tryNativeToHexString(ethCircleRelayer.address, CHAIN_ID_SEPOLIA);

// register the emitter
const receipt = await avaxCircleRelayer
.registerContract(CHAIN_ID_ETH, targetContractAddressHex)
.registerContract(CHAIN_ID_SEPOLIA, targetContractAddressHex)
.then((tx: ethers.ContractTransaction) => tx.wait())
.catch((msg: any) => {
// should not happen
@@ -239,15 +240,15 @@ describe("Circle Integration Test", () => {

// query the contract and confirm that the contract address is set in storage
const emitterInContractState =
await avaxCircleRelayer.getRegisteredContract(CHAIN_ID_ETH);
await avaxCircleRelayer.getRegisteredContract(CHAIN_ID_SEPOLIA);
expect(emitterInContractState).to.equal(targetContractAddressHex);
});

it("Should Set Target Relayer Fee for USDC", async () => {
// set the relayer fee for USDC
const receipt = await avaxCircleRelayer
.connect(avaxOwnerAssistantWallet)
.updateRelayerFee(CHAIN_ID_ETH, avaxUsdc.address, ethRelayerFee)
.updateRelayerFee(CHAIN_ID_SEPOLIA, avaxUsdc.address, ethRelayerFee)
.then((tx: ethers.ContractTransaction) => tx.wait())
.catch((msg: any) => {
// should not happen
@@ -258,7 +259,7 @@ describe("Circle Integration Test", () => {

// check contract state
const relayerFeeInState = await avaxCircleRelayer.relayerFee(
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
avaxUsdc.address
);
expect(relayerFeeInState.toString()).to.equal(ethRelayerFee.toString());
@@ -313,6 +314,55 @@ describe("Circle Integration Test", () => {
);
});
});

describe("MessageFee", () => {

it("Transfer Tokens With Relay - WH messageFee is higher than 0", async () => {
const amountFromEth = ethers.BigNumber.from("6900000");
const toNativeTokenAmountEth = ethers.BigNumber.from("500000");
const targetRecipientWallet =
"0x" + tryNativeToHexString(avaxWallet.address, "avalanche");

// sets messageFee to 0.001
const newMessageFee = ethers.utils.parseEther("0.001");
const wormholeAddress = await ethCircleIntegration.wormhole()
const wormholeBalanceBefore = await ethProvider.getBalance(wormholeAddress)
const wormhole = IWormhole__factory.connect(wormholeAddress, ethWallet)
await ethProvider.send("anvil_setStorageAt", [
wormholeAddress,
7, // messageFee storage slot
ethers.utils.hexZeroPad(newMessageFee.toHexString(), 32)
]);
const messageFee = await wormhole.messageFee();
await ethUsdc
.approve(ethCircleRelayer.address, amountFromEth)
.then((tx) => tx.wait());
const receipt = await ethCircleRelayer
.transferTokensWithRelay(
ethUsdc.address,
amountFromEth,
toNativeTokenAmountEth,
CHAIN_ID_AVAX,
targetRecipientWallet,
{
value: newMessageFee
}
)
await receipt.wait()
const wormholeBalanceAfter = await ethProvider.getBalance(wormholeAddress)
// sets messageFee back to 0
await ethProvider.send("anvil_setStorageAt", [
wormholeAddress,
7, // messageFee storage slot
ethers.utils.hexZeroPad('0x0', 32)
]);
const messageFeeAfter = await wormhole.messageFee()
expect(messageFee.eq(newMessageFee)).to.be.true;
expect(messageFeeAfter.eq(ethers.BigNumber.from('0'))).to.be.true;
expect(wormholeBalanceAfter.sub(wormholeBalanceBefore).eq(newMessageFee)).to.be.true;
})
})

describe("Transfer Tokens With Relay Logic", () => {
// amounts from Ethereum
const amountFromEth = ethers.BigNumber.from("6900000");
@@ -381,7 +431,7 @@ describe("Circle Integration Test", () => {
findWormholeMessageInLogs(
receipt!.logs,
address,
CHAIN_ID_ETH as number
CHAIN_ID_SEPOLIA as number
)
);
expect(wormholeMessage).is.not.null;
@@ -540,7 +590,7 @@ describe("Circle Integration Test", () => {
avaxUsdc.address,
amountFromAvax,
toNativeTokenAmountAvax,
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
targetRecipientWallet
)
.then(async (tx) => {
@@ -670,7 +720,7 @@ describe("Circle Integration Test", () => {

// fetch the relayer fee
const relayerFee = await avaxCircleRelayer.relayerFee(
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
avaxUsdc.address
);

@@ -735,7 +785,7 @@ describe("Circle Integration Test", () => {
avaxUsdc.address,
amountFromAvax,
toNativeTokenAmountAvax,
CHAIN_ID_ETH,
CHAIN_ID_SEPOLIA,
targetRecipientWallet
)
.then(async (tx) => {
6 changes: 3 additions & 3 deletions evm/ts/test/helpers/consts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ethers} from "ethers";

// ethereum goerli testnet fork
export const ETH_LOCALHOST = "http://localhost:8546";
// ethereum sepolia testnet fork
export const ETH_LOCALHOST = "http://127.0.0.1:8546";
export const ETH_FORK_CHAIN_ID = Number(process.env.ETH_FORK_CHAIN_ID!);
export const ETH_WORMHOLE_ADDRESS = process.env.ETH_WORMHOLE_ADDRESS!;
export const ETH_USDC_TOKEN_ADDRESS = process.env.ETH_USDC_TOKEN_ADDRESS!;
@@ -10,7 +10,7 @@ export const ETH_CIRCLE_INTEGRATION_ADDRESS =
process.env.ETH_CIRCLE_INTEGRATION_ADDRESS!;

// avalanche fuji testnet fork
export const AVAX_LOCALHOST = "http://localhost:8547";
export const AVAX_LOCALHOST = "http://127.0.0.1:8547";
export const AVAX_FORK_CHAIN_ID = Number(process.env.AVAX_FORK_CHAIN_ID!);
export const AVAX_WORMHOLE_ADDRESS = process.env.AVAX_WORMHOLE_ADDRESS!;
export const AVAX_USDC_TOKEN_ADDRESS = process.env.AVAX_USDC_TOKEN_ADDRESS!;
Loading