Commit 45fdc8d1 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into jg/rate_limit_p2p_unsafe_sync_requests

parents e3e4ddb9 846be4eb
---
'@eth-optimism/sdk': patch
---
add eco bridge adapter
---
'@eth-optimism/contracts-periphery': patch
---
Change type for auth id on Faucet contracts from bytes to bytes32
...@@ -564,12 +564,12 @@ jobs: ...@@ -564,12 +564,12 @@ jobs:
name: anvil-l1 name: anvil-l1
background: true background: true
# atm this is goerli but we should use mainnet after bedrock is live # atm this is goerli but we should use mainnet after bedrock is live
command: anvil --fork-url $ANVIL_L1_FORK_URL --fork-block-number 8847426 command: anvil --fork-url $ANVIL_L1_FORK_URL --fork-block-number 9023108
- run: - run:
name: anvil-l2 name: anvil-l2
background: true background: true
# atm this is goerli but we should use mainnet after bedrock is live # atm this is goerli but we should use mainnet after bedrock is live
command: anvil --fork-url $ANVIL_L2_FORK_URL --port 9545 --fork-block-number 8172732 command: anvil --fork-url $ANVIL_L2_FORK_URL --port 9545 --fork-block-number 9504811
- run: - run:
name: build name: build
command: yarn build command: yarn build
...@@ -586,7 +586,7 @@ jobs: ...@@ -586,7 +586,7 @@ jobs:
command: npx wait-on tcp:9545 && cast block-number --rpc-url http://localhost:9545 command: npx wait-on tcp:9545 && cast block-number --rpc-url http://localhost:9545
- run: - run:
name: test:next name: test:next
command: yarn test:next command: yarn test:next:run
no_output_timeout: 5m no_output_timeout: 5m
working_directory: packages/sdk working_directory: packages/sdk
environment: environment:
......
...@@ -80,7 +80,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -80,7 +80,7 @@ contract AdminFaucetAuthModuleTest is Test {
uint256 _eip712Chainid, uint256 _eip712Chainid,
address _eip712VerifyingContract, address _eip712VerifyingContract,
address recipient, address recipient,
bytes memory id, bytes32 id,
bytes32 nonce bytes32 nonce
) internal view returns (bytes memory) { ) internal view returns (bytes memory) {
AdminFaucetAuthModule.Proof memory proof = AdminFaucetAuthModule.Proof( AdminFaucetAuthModule.Proof memory proof = AdminFaucetAuthModule.Proof(
...@@ -114,7 +114,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -114,7 +114,7 @@ contract AdminFaucetAuthModuleTest is Test {
block.chainid, block.chainid,
address(adminFam), address(adminFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
...@@ -122,7 +122,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -122,7 +122,7 @@ contract AdminFaucetAuthModuleTest is Test {
assertEq( assertEq(
adminFam.verify( adminFam.verify(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
proof proof
), ),
true true
...@@ -142,7 +142,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -142,7 +142,7 @@ contract AdminFaucetAuthModuleTest is Test {
block.chainid, block.chainid,
address(adminFam), address(adminFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
...@@ -150,7 +150,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -150,7 +150,7 @@ contract AdminFaucetAuthModuleTest is Test {
assertEq( assertEq(
adminFam.verify( adminFam.verify(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
proof proof
), ),
false false
...@@ -172,7 +172,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -172,7 +172,7 @@ contract AdminFaucetAuthModuleTest is Test {
block.chainid, block.chainid,
address(adminFam), address(adminFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
...@@ -180,7 +180,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -180,7 +180,7 @@ contract AdminFaucetAuthModuleTest is Test {
assertEq( assertEq(
adminFam.verify( adminFam.verify(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
abi.encodePacked(randomAddress), keccak256(abi.encodePacked(randomAddress)),
proof proof
), ),
false false
......
...@@ -9,7 +9,7 @@ import { FaucetHelper } from "../testing/helpers/FaucetHelper.sol"; ...@@ -9,7 +9,7 @@ import { FaucetHelper } from "../testing/helpers/FaucetHelper.sol";
contract Faucet_Initializer is Test { contract Faucet_Initializer is Test {
event Drip( event Drip(
string indexed authModule, string indexed authModule,
bytes indexed userId, bytes32 indexed userId,
uint256 amount, uint256 amount,
address indexed recipient address indexed recipient
); );
...@@ -103,7 +103,7 @@ contract Faucet_Initializer is Test { ...@@ -103,7 +103,7 @@ contract Faucet_Initializer is Test {
uint256 _eip712Chainid, uint256 _eip712Chainid,
address _eip712VerifyingContract, address _eip712VerifyingContract,
address recipient, address recipient,
bytes memory id, bytes32 id,
bytes32 nonce bytes32 nonce
) internal view returns (bytes memory) { ) internal view returns (bytes memory) {
AdminFaucetAuthModule.Proof memory proof = AdminFaucetAuthModule.Proof( AdminFaucetAuthModule.Proof memory proof = AdminFaucetAuthModule.Proof(
...@@ -140,14 +140,18 @@ contract FaucetTest is Faucet_Initializer { ...@@ -140,14 +140,18 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(optimistNftFam), address(optimistNftFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
vm.prank(nonAdmin); vm.prank(nonAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(optimistNftFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(
optimistNftFam,
keccak256(abi.encodePacked(fundsReceiver)),
signature
)
); );
} }
...@@ -161,7 +165,7 @@ contract FaucetTest is Faucet_Initializer { ...@@ -161,7 +165,7 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(optimistNftFam), address(optimistNftFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
...@@ -169,7 +173,11 @@ contract FaucetTest is Faucet_Initializer { ...@@ -169,7 +173,11 @@ contract FaucetTest is Faucet_Initializer {
vm.expectRevert("Faucet: drip parameters could not be verified by security module"); vm.expectRevert("Faucet: drip parameters could not be verified by security module");
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(optimistNftFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(
optimistNftFam,
keccak256(abi.encodePacked(fundsReceiver)),
signature
)
); );
} }
...@@ -183,7 +191,7 @@ contract FaucetTest is Faucet_Initializer { ...@@ -183,7 +191,7 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(optimistNftFam), address(optimistNftFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
...@@ -191,7 +199,11 @@ contract FaucetTest is Faucet_Initializer { ...@@ -191,7 +199,11 @@ contract FaucetTest is Faucet_Initializer {
vm.prank(nonAdmin); vm.prank(nonAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(optimistNftFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(
optimistNftFam,
keccak256(abi.encodePacked(fundsReceiver)),
signature
)
); );
uint256 recipientBalanceAfter = address(fundsReceiver).balance; uint256 recipientBalanceAfter = address(fundsReceiver).balance;
assertEq( assertEq(
...@@ -211,7 +223,7 @@ contract FaucetTest is Faucet_Initializer { ...@@ -211,7 +223,7 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
...@@ -219,7 +231,7 @@ contract FaucetTest is Faucet_Initializer { ...@@ -219,7 +231,7 @@ contract FaucetTest is Faucet_Initializer {
vm.prank(nonAdmin); vm.prank(nonAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
); );
uint256 recipientBalanceAfter = address(fundsReceiver).balance; uint256 recipientBalanceAfter = address(fundsReceiver).balance;
assertEq( assertEq(
...@@ -239,17 +251,22 @@ contract FaucetTest is Faucet_Initializer { ...@@ -239,17 +251,22 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
vm.expectEmit(true, true, true, true, address(faucet)); vm.expectEmit(true, true, true, true, address(faucet));
emit Drip("GithubModule", abi.encodePacked(fundsReceiver), .05 ether, fundsReceiver); emit Drip(
"GithubModule",
keccak256(abi.encodePacked(fundsReceiver)),
.05 ether,
fundsReceiver
);
vm.prank(nonAdmin); vm.prank(nonAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
); );
} }
...@@ -263,14 +280,14 @@ contract FaucetTest is Faucet_Initializer { ...@@ -263,14 +280,14 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
vm.startPrank(faucetContractAdmin); vm.startPrank(faucetContractAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
); );
faucet.configure(githubFam, Faucet.ModuleConfig("GithubModule", false, 1 days, .05 ether)); faucet.configure(githubFam, Faucet.ModuleConfig("GithubModule", false, 1 days, .05 ether));
...@@ -278,7 +295,7 @@ contract FaucetTest is Faucet_Initializer { ...@@ -278,7 +295,7 @@ contract FaucetTest is Faucet_Initializer {
vm.expectRevert("Faucet: provided auth module is not supported by this faucet"); vm.expectRevert("Faucet: provided auth module is not supported by this faucet");
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
); );
vm.stopPrank(); vm.stopPrank();
} }
...@@ -293,20 +310,20 @@ contract FaucetTest is Faucet_Initializer { ...@@ -293,20 +310,20 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce nonce
); );
vm.startPrank(faucetContractAdmin); vm.startPrank(faucetContractAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
); );
vm.expectRevert("Faucet: nonce has already been used"); vm.expectRevert("Faucet: nonce has already been used");
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
); );
vm.stopPrank(); vm.stopPrank();
} }
...@@ -321,14 +338,14 @@ contract FaucetTest is Faucet_Initializer { ...@@ -321,14 +338,14 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce0 nonce0
); );
vm.startPrank(faucetContractAdmin); vm.startPrank(faucetContractAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce0), Faucet.DripParameters(payable(fundsReceiver), nonce0),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature0) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature0)
); );
bytes32 nonce1 = faucetHelper.consumeNonce(); bytes32 nonce1 = faucetHelper.consumeNonce();
...@@ -339,14 +356,14 @@ contract FaucetTest is Faucet_Initializer { ...@@ -339,14 +356,14 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce1 nonce1
); );
vm.expectRevert("Faucet: auth cannot be used yet because timeout has not elapsed"); vm.expectRevert("Faucet: auth cannot be used yet because timeout has not elapsed");
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce1), Faucet.DripParameters(payable(fundsReceiver), nonce1),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature1) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature1)
); );
vm.stopPrank(); vm.stopPrank();
} }
...@@ -361,14 +378,14 @@ contract FaucetTest is Faucet_Initializer { ...@@ -361,14 +378,14 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce0 nonce0
); );
vm.startPrank(faucetContractAdmin); vm.startPrank(faucetContractAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce0), Faucet.DripParameters(payable(fundsReceiver), nonce0),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature0) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature0)
); );
bytes32 nonce1 = faucetHelper.consumeNonce(); bytes32 nonce1 = faucetHelper.consumeNonce();
...@@ -379,14 +396,14 @@ contract FaucetTest is Faucet_Initializer { ...@@ -379,14 +396,14 @@ contract FaucetTest is Faucet_Initializer {
block.chainid, block.chainid,
address(githubFam), address(githubFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), keccak256(abi.encodePacked(fundsReceiver)),
nonce1 nonce1
); );
vm.warp(startingTimestamp + 1 days + 1 seconds); vm.warp(startingTimestamp + 1 days + 1 seconds);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce1), Faucet.DripParameters(payable(fundsReceiver), nonce1),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature1) Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature1)
); );
vm.stopPrank(); vm.stopPrank();
} }
......
...@@ -16,7 +16,7 @@ contract FaucetHelper { ...@@ -16,7 +16,7 @@ contract FaucetHelper {
* @notice EIP712 typehash for the Proof type. * @notice EIP712 typehash for the Proof type.
*/ */
bytes32 public constant PROOF_TYPEHASH = bytes32 public constant PROOF_TYPEHASH =
keccak256("Proof(address recipient,bytes32 nonce,bytes id)"); keccak256("Proof(address recipient,bytes32 nonce,bytes32 id)");
/** /**
* @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature. * @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature.
......
...@@ -31,7 +31,7 @@ contract Faucet { ...@@ -31,7 +31,7 @@ contract Faucet {
*/ */
event Drip( event Drip(
string indexed authModule, string indexed authModule,
bytes indexed userId, bytes32 indexed userId,
uint256 amount, uint256 amount,
address indexed recipient address indexed recipient
); );
...@@ -49,7 +49,7 @@ contract Faucet { ...@@ -49,7 +49,7 @@ contract Faucet {
*/ */
struct AuthParameters { struct AuthParameters {
IFaucetAuthModule module; IFaucetAuthModule module;
bytes id; bytes32 id;
bytes proof; bytes proof;
} }
...@@ -76,12 +76,12 @@ contract Faucet { ...@@ -76,12 +76,12 @@ contract Faucet {
/** /**
* @notice Mapping of authentication IDs to the next timestamp at which they can be used. * @notice Mapping of authentication IDs to the next timestamp at which they can be used.
*/ */
mapping(IFaucetAuthModule => mapping(bytes => uint256)) public timeouts; mapping(IFaucetAuthModule => mapping(bytes32 => uint256)) public timeouts;
/** /**
* @notice Maps from id to nonces to whether or not they have been used. * @notice Maps from id to nonces to whether or not they have been used.
*/ */
mapping(bytes => mapping(bytes32 => bool)) public nonces; mapping(bytes32 => mapping(bytes32 => bool)) public nonces;
/** /**
* @notice Modifier that makes a function admin priviledged. * @notice Modifier that makes a function admin priviledged.
......
...@@ -21,7 +21,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 { ...@@ -21,7 +21,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 {
* @notice EIP712 typehash for the Proof type. * @notice EIP712 typehash for the Proof type.
*/ */
bytes32 public constant PROOF_TYPEHASH = bytes32 public constant PROOF_TYPEHASH =
keccak256("Proof(address recipient,bytes32 nonce,bytes id)"); keccak256("Proof(address recipient,bytes32 nonce,bytes32 id)");
/** /**
* @notice Struct that represents a proof that verifies the admin. * @notice Struct that represents a proof that verifies the admin.
...@@ -33,7 +33,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 { ...@@ -33,7 +33,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 {
struct Proof { struct Proof {
address recipient; address recipient;
bytes32 nonce; bytes32 nonce;
bytes id; bytes32 id;
} }
/** /**
...@@ -54,7 +54,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 { ...@@ -54,7 +54,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 {
*/ */
function verify( function verify(
Faucet.DripParameters memory _params, Faucet.DripParameters memory _params,
bytes memory _id, bytes32 _id,
bytes memory _proof bytes memory _proof
) external view returns (bool) { ) external view returns (bool) {
// Generate a EIP712 typed data hash to compare against the proof. // Generate a EIP712 typed data hash to compare against the proof.
......
...@@ -17,7 +17,7 @@ interface IFaucetAuthModule { ...@@ -17,7 +17,7 @@ interface IFaucetAuthModule {
*/ */
function verify( function verify(
Faucet.DripParameters memory _params, Faucet.DripParameters memory _params,
bytes memory _id, bytes32 _id,
bytes memory _proof bytes memory _proof
) external view returns (bool); ) external view returns (bool);
} }
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
"lint:fix": "yarn lint:check --fix", "lint:fix": "yarn lint:check --fix",
"pre-commit": "lint-staged", "pre-commit": "lint-staged",
"test": "hardhat test", "test": "hardhat test",
"test:next": "vitest test-next/proveMessage.spec.ts", "test:next": "vitest",
"test:next:run": "vitest run",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json", "test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json",
"autogen:docs": "typedoc --out docs src/index.ts" "autogen:docs": "typedoc --out docs src/index.ts"
}, },
...@@ -48,7 +49,9 @@ ...@@ -48,7 +49,9 @@
"typedoc": "^0.22.13", "typedoc": "^0.22.13",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"vitest": "^0.28.3", "vitest": "^0.28.3",
"zod": "^3.11.6" "zod": "^3.11.6",
"viem": "^0.3.30",
"isomorphic-fetch": "^3.0.0"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/contracts": "0.5.40", "@eth-optimism/contracts": "0.5.40",
......
import fetch from 'isomorphic-fetch'
// viem needs this
global.fetch = fetch
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Contract } from 'ethers'
import { hexStringEquals } from '@eth-optimism/core-utils'
import { AddressLike } from '../interfaces'
import { toAddress } from '../utils'
import { StandardBridgeAdapter } from './standard-bridge'
/**
* Bridge adapter for ECO.
* ECO bridge requires a separate adapter as exposes different functions than our standard bridge
*/
export class ECOBridgeAdapter extends StandardBridgeAdapter {
public async supportsTokenPair(
l1Token: AddressLike,
l2Token: AddressLike
): Promise<boolean> {
const l1Bridge = new Contract(
this.l1Bridge.address,
[
{
inputs: [],
name: 'ecoAddress',
outputs: [
{
internalType: 'address',
name: '',
type: 'address',
},
],
stateMutability: 'view',
type: 'function',
},
],
this.messenger.l1Provider
)
const l2Bridge = new Contract(
this.l2Bridge.address,
[
{
inputs: [],
name: 'l2EcoToken',
outputs: [
{
internalType: 'contract L2ECO',
name: '',
type: 'address',
},
],
stateMutability: 'view',
type: 'function',
},
],
this.messenger.l2Provider
)
const [remoteL1Token, remoteL2Token] = await Promise.all([
l1Bridge.ecoAddress(),
l2Bridge.l2EcoToken(),
])
if (!hexStringEquals(remoteL1Token, toAddress(l1Token))) {
return false
}
if (!hexStringEquals(remoteL2Token, toAddress(l2Token))) {
return false
}
return true
}
}
export * from './standard-bridge' export * from './standard-bridge'
export * from './eth-bridge' export * from './eth-bridge'
export * from './dai-bridge' export * from './dai-bridge'
export * from './eco-bridge'
...@@ -12,7 +12,11 @@ import { ...@@ -12,7 +12,11 @@ import {
OEL2ContractsLike, OEL2ContractsLike,
BridgeAdapterData, BridgeAdapterData,
} from '../interfaces' } from '../interfaces'
import { StandardBridgeAdapter, DAIBridgeAdapter } from '../adapters' import {
StandardBridgeAdapter,
DAIBridgeAdapter,
ECOBridgeAdapter,
} from '../adapters'
export const DEPOSIT_CONFIRMATION_BLOCKS: { export const DEPOSIT_CONFIRMATION_BLOCKS: {
[ChainID in L2ChainID]: number [ChainID in L2ChainID]: number
...@@ -205,5 +209,10 @@ export const BRIDGE_ADAPTER_DATA: { ...@@ -205,5 +209,10 @@ export const BRIDGE_ADAPTER_DATA: {
l1Bridge: '0x05a388Db09C2D44ec0b00Ee188cD42365c42Df23' as const, l1Bridge: '0x05a388Db09C2D44ec0b00Ee188cD42365c42Df23' as const,
l2Bridge: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65' as const, l2Bridge: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65' as const,
}, },
ECO: {
Adapter: ECOBridgeAdapter,
l1Bridge: '0x7a01E277B8fDb8CDB2A2258508514716359f44A0' as const,
l2Bridge: '0x7a01E277B8fDb8CDB2A2258508514716359f44A0' as const,
},
}, },
} }
import ethers from 'ethers'
import { describe, expect, it } from 'vitest'
import { Address, PublicClient, parseEther } from 'viem'
import {
l1TestClient,
l2TestClient,
l1PublicClient,
l2PublicClient,
} from './testUtils/viemClients'
import { BRIDGE_ADAPTER_DATA, CrossChainMessenger, L2ChainID } from '../src'
import { l1Provider, l2Provider } from './testUtils/ethersProviders'
const ECO_WHALE: Address = '0xBd11c836279a1352ce737FbBFba36b20734B04e7'
// we should instead use tokenlist as source of truth
const ECO_L1_TOKEN_ADDRESS: Address =
'0x3E87d4d9E69163E7590f9b39a70853cf25e5ABE3'
const ECO_L2_TOKEN_ADDRESS: Address =
'0x54bBECeA38ff36D32323f8A754683C1F5433A89f'
const getERC20TokenBalance = async (
publicClient: PublicClient,
tokenAddress: Address,
ownerAddress: Address
) => {
const result = await publicClient.readContract({
address: tokenAddress,
abi: [
{
inputs: [{ name: 'owner', type: 'address' }],
name: 'balanceOf',
outputs: [{ name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
],
functionName: 'balanceOf',
args: [ownerAddress],
})
return result as bigint
}
const getL1ERC20TokenBalance = async (ownerAddress: Address) => {
return getERC20TokenBalance(
l1PublicClient,
ECO_L1_TOKEN_ADDRESS,
ownerAddress
)
}
const getL2ERC20TokenBalance = async (ownerAddress: Address) => {
return getERC20TokenBalance(
l2PublicClient,
ECO_L2_TOKEN_ADDRESS,
ownerAddress
)
}
describe('ECO token', () => {
it('sdk should be able to deposit to l1 bridge contract correctly', async () => {
await l1TestClient.impersonateAccount({ address: ECO_WHALE })
const l1EcoWhaleSigner = await l1Provider.getSigner(ECO_WHALE)
const preBridgeL1EcoWhaleBalance = await getL1ERC20TokenBalance(ECO_WHALE)
const crossChainMessenger = new CrossChainMessenger({
l1SignerOrProvider: l1EcoWhaleSigner,
l2SignerOrProvider: l2Provider,
l1ChainId: 5,
l2ChainId: 420,
bedrock: true,
bridges: BRIDGE_ADAPTER_DATA[L2ChainID.OPTIMISM_GOERLI],
})
await crossChainMessenger.approveERC20(
ECO_L1_TOKEN_ADDRESS,
ECO_L2_TOKEN_ADDRESS,
ethers.utils.parseEther('0.1')
)
const txResponse = await crossChainMessenger.depositERC20(
ECO_L1_TOKEN_ADDRESS,
ECO_L2_TOKEN_ADDRESS,
ethers.utils.parseEther('0.1')
)
await txResponse.wait()
const l1EcoWhaleBalance = await getL1ERC20TokenBalance(ECO_WHALE)
expect(l1EcoWhaleBalance).toEqual(
preBridgeL1EcoWhaleBalance - parseEther('0.1')
)
}, 20_000)
it('sdk should be able to withdraw into the l2 bridge contract correctly', async () => {
await l2TestClient.impersonateAccount({ address: ECO_WHALE })
const l2EcoWhaleSigner = await l2Provider.getSigner(ECO_WHALE)
const preBridgeL2EcoWhaleBalance = await getL2ERC20TokenBalance(ECO_WHALE)
const crossChainMessenger = new CrossChainMessenger({
l1SignerOrProvider: l1Provider,
l2SignerOrProvider: l2EcoWhaleSigner,
l1ChainId: 5,
l2ChainId: 420,
bedrock: true,
bridges: BRIDGE_ADAPTER_DATA[L2ChainID.OPTIMISM_GOERLI],
})
const txResponse = await crossChainMessenger.withdrawERC20(
ECO_L1_TOKEN_ADDRESS,
ECO_L2_TOKEN_ADDRESS,
ethers.utils.parseEther('0.1')
)
await txResponse.wait()
const l2EcoWhaleBalance = await getL2ERC20TokenBalance(ECO_WHALE)
expect(l2EcoWhaleBalance).toEqual(
preBridgeL2EcoWhaleBalance - parseEther('0.1')
)
}, 20_000)
})
...@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest' ...@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
import { z } from 'zod' import { z } from 'zod'
import { CrossChainMessenger } from '../src' import { CrossChainMessenger } from '../src'
import { l1Provider, l2Provider } from './testUtils/ethersProviders'
/** /**
* This test repros the bug where legacy withdrawals are not provable * This test repros the bug where legacy withdrawals are not provable
...@@ -48,33 +49,12 @@ transactionHash 0xd66fda632b51a8b25a9d260d70da8be57b9930c461637086152633 ...@@ -48,33 +49,12 @@ transactionHash 0xd66fda632b51a8b25a9d260d70da8be57b9930c461637086152633
transactionIndex 0 transactionIndex 0
type type
*/ */
const E2E_RPC_URL_L1 = z
.string()
.url()
.describe('L1 ethereum rpc Url')
.parse(import.meta.env.VITE_E2E_RPC_URL_L1)
const E2E_RPC_URL_L2 = z
.string()
.url()
.describe('L1 ethereum rpc Url')
.parse(import.meta.env.VITE_E2E_RPC_URL_L2)
const E2E_PRIVATE_KEY = z const E2E_PRIVATE_KEY = z
.string() .string()
.describe('Private key') .describe('Private key')
.parse(import.meta.env.VITE_E2E_PRIVATE_KEY) .parse(import.meta.env.VITE_E2E_PRIVATE_KEY)
const jsonRpcHeaders = { 'User-Agent': 'eth-optimism/@gateway/backend' }
/**
* Initialize the signer, prover, and cross chain messenger
*/
const l1Provider = new ethers.providers.JsonRpcProvider({
url: E2E_RPC_URL_L1,
headers: jsonRpcHeaders,
})
const l2Provider = new ethers.providers.JsonRpcProvider({
url: E2E_RPC_URL_L2,
headers: jsonRpcHeaders,
})
const l1Wallet = new ethers.Wallet(E2E_PRIVATE_KEY, l1Provider) const l1Wallet = new ethers.Wallet(E2E_PRIVATE_KEY, l1Provider)
const crossChainMessenger = new CrossChainMessenger({ const crossChainMessenger = new CrossChainMessenger({
l1SignerOrProvider: l1Wallet, l1SignerOrProvider: l1Wallet,
......
import ethers from 'ethers'
import { z } from 'zod'
const E2E_RPC_URL_L1 = z
.string()
.url()
.describe('L1 ethereum rpc Url')
.parse(import.meta.env.VITE_E2E_RPC_URL_L1)
const E2E_RPC_URL_L2 = z
.string()
.url()
.describe('L1 ethereum rpc Url')
.parse(import.meta.env.VITE_E2E_RPC_URL_L2)
const jsonRpcHeaders = { 'User-Agent': 'eth-optimism/@gateway/backend' }
/**
* Initialize the signer, prover, and cross chain messenger
*/
const l1Provider = new ethers.providers.JsonRpcProvider({
url: E2E_RPC_URL_L1,
headers: jsonRpcHeaders,
})
const l2Provider = new ethers.providers.JsonRpcProvider({
url: E2E_RPC_URL_L2,
headers: jsonRpcHeaders,
})
export { l1Provider, l2Provider }
import {
createTestClient,
createPublicClient,
createWalletClient,
http,
} from 'viem'
import { goerli, optimismGoerli } from 'viem/chains'
// we should instead use .env to determine chain so we can support alternate l1/l2 pairs
const L1_CHAIN = goerli
const L2_CHAIN = optimismGoerli
const L1_RPC_URL = 'http://localhost:8545'
const L2_RPC_URL = 'http://localhost:9545'
const l1TestClient = createTestClient({
mode: 'anvil',
chain: L1_CHAIN,
transport: http(L1_RPC_URL),
})
const l2TestClient = createTestClient({
mode: 'anvil',
chain: L2_CHAIN,
transport: http(L2_RPC_URL),
})
const l1PublicClient = createPublicClient({
chain: L1_CHAIN,
transport: http(L1_RPC_URL),
})
const l2PublicClient = createPublicClient({
chain: L2_CHAIN,
transport: http(L2_RPC_URL),
})
const l1WalletClient = createWalletClient({
chain: L1_CHAIN,
transport: http(L1_RPC_URL),
})
const l2WalletClient = createWalletClient({
chain: L2_CHAIN,
transport: http(L2_RPC_URL),
})
export {
l1TestClient,
l2TestClient,
l1PublicClient,
l2PublicClient,
l1WalletClient,
l2WalletClient,
}
import { defineConfig } from 'vitest/config'
// https://vitest.dev/config/ - for docs
export default defineConfig({
test: {
setupFiles: './setupVitest.ts',
include: ['test-next/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
})
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
# yarn lockfile v1 # yarn lockfile v1
"@adraffy/ens-normalize@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d"
integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ==
"@babel/code-frame@7.12.11": "@babel/code-frame@7.12.11":
version "7.12.11" version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
...@@ -3331,6 +3336,13 @@ ...@@ -3331,6 +3336,13 @@
"@motionone/dom" "^10.15.5" "@motionone/dom" "^10.15.5"
tslib "^2.3.1" tslib "^2.3.1"
"@noble/curves@1.0.0", "@noble/curves@~1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932"
integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==
dependencies:
"@noble/hashes" "1.3.0"
"@noble/ed25519@^1.7.0": "@noble/ed25519@^1.7.0":
version "1.7.3" version "1.7.3"
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123" resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123"
...@@ -3341,6 +3353,11 @@ ...@@ -3341,6 +3353,11 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae"
integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==
"@noble/hashes@1.3.0", "@noble/hashes@~1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1"
integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==
"@noble/hashes@^1.1.2": "@noble/hashes@^1.1.2":
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12"
...@@ -3772,6 +3789,11 @@ ...@@ -3772,6 +3789,11 @@
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7"
integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA== integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA==
"@scure/base@~1.1.0":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
"@scure/bip32@1.0.1": "@scure/bip32@1.0.1":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.0.1.tgz#1409bdf9f07f0aec99006bb0d5827693418d3aa5" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.0.1.tgz#1409bdf9f07f0aec99006bb0d5827693418d3aa5"
...@@ -3781,6 +3803,15 @@ ...@@ -3781,6 +3803,15 @@
"@noble/secp256k1" "~1.5.2" "@noble/secp256k1" "~1.5.2"
"@scure/base" "~1.0.0" "@scure/base" "~1.0.0"
"@scure/bip32@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87"
integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==
dependencies:
"@noble/curves" "~1.0.0"
"@noble/hashes" "~1.3.0"
"@scure/base" "~1.1.0"
"@scure/bip39@1.0.0": "@scure/bip39@1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.0.0.tgz#47504e58de9a56a4bbed95159d2d6829fa491bb0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.0.0.tgz#47504e58de9a56a4bbed95159d2d6829fa491bb0"
...@@ -3789,6 +3820,14 @@ ...@@ -3789,6 +3820,14 @@
"@noble/hashes" "~1.0.0" "@noble/hashes" "~1.0.0"
"@scure/base" "~1.0.0" "@scure/base" "~1.0.0"
"@scure/bip39@1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b"
integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==
dependencies:
"@noble/hashes" "~1.3.0"
"@scure/base" "~1.1.0"
"@sentry/core@5.30.0": "@sentry/core@5.30.0":
version "5.30.0" version "5.30.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3"
...@@ -4970,6 +5009,11 @@ ...@@ -4970,6 +5009,11 @@
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.36.tgz#35e11200542cf29068ba787dad57da9bdb82f644" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.36.tgz#35e11200542cf29068ba787dad57da9bdb82f644"
integrity sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ== integrity sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==
"@wagmi/chains@0.2.16":
version "0.2.16"
resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.2.16.tgz#a726716e4619ec1c192b312e23f9c38407617aa0"
integrity sha512-rkWaI2PxCnbD8G07ZZff5QXftnSkYL0h5f4DkHCG3fGYYr/ZDvmCL4bMae7j7A9sAif1csPPBmbCzHp3R5ogCQ==
"@wagmi/chains@0.2.8": "@wagmi/chains@0.2.8":
version "0.2.8" version "0.2.8"
resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.2.8.tgz#eece43702f719d7de4193dc993668e0d783937b5" resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.2.8.tgz#eece43702f719d7de4193dc993668e0d783937b5"
...@@ -5500,6 +5544,11 @@ abbrev@1.0.x: ...@@ -5500,6 +5544,11 @@ abbrev@1.0.x:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU=
abitype@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.2.tgz#cacd330d07488a4020d84f54fc361361234b9c83"
integrity sha512-B1ViNMGpfx/qjVQi0RTc2HEFHuR9uoCoTEkwELT5Y7pBPtBbctYijz9BK6+Kd0hQ3S70FhYTO2dWWk0QNUEXMA==
abitype@^0.3.0: abitype@^0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.3.0.tgz#75150e337d88cc0b2423ed0d3fc36935f139d04c" resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.3.0.tgz#75150e337d88cc0b2423ed0d3fc36935f139d04c"
...@@ -13482,6 +13531,19 @@ isobject@^3.0.0, isobject@^3.0.1: ...@@ -13482,6 +13531,19 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
isomorphic-fetch@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4"
integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==
dependencies:
node-fetch "^2.6.1"
whatwg-fetch "^3.4.1"
isomorphic-ws@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf"
integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==
isomorphic-ws@^4.0.1: isomorphic-ws@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc"
...@@ -21526,6 +21588,21 @@ vfile@^4.0.0: ...@@ -21526,6 +21588,21 @@ vfile@^4.0.0:
unist-util-stringify-position "^2.0.0" unist-util-stringify-position "^2.0.0"
vfile-message "^2.0.0" vfile-message "^2.0.0"
viem@^0.3.30:
version "0.3.30"
resolved "https://registry.yarnpkg.com/viem/-/viem-0.3.30.tgz#7421bbff8b21c2e6aa90634a18d57b9612e90555"
integrity sha512-4jokEVR2vtDl6zSpZiPUaHviK2dzW6uxCAVUArlh0Jhrc4ms0dkhn5E4iwk1CWMto8+YeLFEgY4gr9P10ryoEQ==
dependencies:
"@adraffy/ens-normalize" "1.9.0"
"@noble/curves" "1.0.0"
"@noble/hashes" "1.3.0"
"@scure/bip32" "1.3.0"
"@scure/bip39" "1.2.0"
"@wagmi/chains" "0.2.16"
abitype "0.8.2"
isomorphic-ws "5.0.0"
ws "8.12.0"
vite-node@0.28.3: vite-node@0.28.3:
version "0.28.3" version "0.28.3"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.28.3.tgz#5d693c237d5467f167f81d158a56d3408fea899c" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.28.3.tgz#5d693c237d5467f167f81d158a56d3408fea899c"
...@@ -22173,6 +22250,11 @@ whatwg-fetch@^2.0.4: ...@@ -22173,6 +22250,11 @@ whatwg-fetch@^2.0.4:
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==
whatwg-fetch@^3.4.1:
version "3.6.2"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
whatwg-mimetype@^3.0.0: whatwg-mimetype@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7"
...@@ -22446,6 +22528,11 @@ ws@7.5.3, ws@^7.4.6: ...@@ -22446,6 +22528,11 @@ ws@7.5.3, ws@^7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==
ws@8.12.0:
version "8.12.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8"
integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==
ws@^3.0.0: ws@^3.0.0:
version "3.3.3" version "3.3.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment