feat: design ens verification flow (#193)

* wip: add base solidity functions to try ens validation

* chore: add hardhat fork setup with env variable

* wip: setup ens verification for FleekERC721

* wip: add ens namehash generation

* chore: gas report setting

* feat: add ens verification on setTokenENS function

* test: hardhat transfer ens owner to set new ens

* test: fix foundry tests to enable ens validation

* refactor: change back ens to calldata and split out a public function for namehash testing

* refactor: move FleekENS.sol to util folder

* test: add ens validation tests for not owner attempts

* chore: add mainnet api key env in ci

* chore: fix .env.example

* fix: remove extra unused file
This commit is contained in:
Felipe Mendes 2023-04-05 11:48:56 -03:00 committed by GitHub
parent 2225b301ff
commit 83cd36dfc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 291 additions and 23 deletions

View File

@ -11,6 +11,8 @@ on:
jobs: jobs:
test-contracts: test-contracts:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
MAINNET_API_KEY: ${{ secrets.MAINNET_API_KEY }}
defaults: defaults:
run: run:

View File

@ -9,4 +9,13 @@ PRIVATE_KEY=
POLYSCAN_API=https://mumbai.polygonscan.com/ POLYSCAN_API=https://mumbai.polygonscan.com/
# The address of the deployed contract on the blockchain # The address of the deployed contract on the blockchain
CONTRACT_ADDRESS= CONTRACT_ADDRESS=
# Alchemy or Infura API key to fork the mainnet on tests (e.g. https://eth-mainnet.g.alchemy.com/v2/your-api-key)
MAINNET_API_KEY=
# Enable gas report on hardhat tests
REPORT_GAS=true
# The CoinMarketCap API key to get the price of the token for gas report
COINMARKETCAP_KEY=

View File

@ -2,10 +2,11 @@
cache cache
artifacts artifacts
deployments/hardhat deployments/hardhat
gas-report
# Foundry # Foundry
out out
forge-cache forge-cache
# OpenZeppelin # OpenZeppelin
.openzeppelin/unknown-*.json .openzeppelin/unknown-*.json

View File

@ -9,6 +9,7 @@ import "./FleekAccessControl.sol";
import "./FleekBilling.sol"; import "./FleekBilling.sol";
import "./FleekPausable.sol"; import "./FleekPausable.sol";
import "./FleekAccessPoints.sol"; import "./FleekAccessPoints.sol";
import "./util/FleekENS.sol";
import "./util/FleekStrings.sol"; import "./util/FleekStrings.sol";
import "./IERCX.sol"; import "./IERCX.sol";
@ -104,7 +105,7 @@ contract FleekERC721 is
string memory name, string memory name,
string memory description, string memory description,
string memory externalURL, string memory externalURL,
string memory ENS, string calldata ens,
string memory commitHash, string memory commitHash,
string memory gitRepository, string memory gitRepository,
string memory logo, string memory logo,
@ -112,6 +113,7 @@ contract FleekERC721 is
bool accessPointAutoApproval, bool accessPointAutoApproval,
address verifier address verifier
) public payable requirePayment(Billing.Mint) returns (uint256) { ) public payable requirePayment(Billing.Mint) returns (uint256) {
FleekENS.requireENSOwner(ens);
uint256 tokenId = _appIds; uint256 tokenId = _appIds;
_mint(to, tokenId); _mint(to, tokenId);
@ -121,7 +123,7 @@ contract FleekERC721 is
app.name = name; app.name = name;
app.description = description; app.description = description;
app.externalURL = externalURL; app.externalURL = externalURL;
app.ENS = ENS; app.ENS = ens;
app.logo = logo; app.logo = logo;
app.color = color; app.color = color;
@ -134,7 +136,7 @@ contract FleekERC721 is
name, name,
description, description,
externalURL, externalURL,
ENS, ens,
commitHash, commitHash,
gitRepository, gitRepository,
logo, logo,
@ -274,8 +276,9 @@ contract FleekERC721 is
*/ */
function setTokenENS( function setTokenENS(
uint256 tokenId, uint256 tokenId,
string memory _tokenENS string calldata _tokenENS
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) { ) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
FleekENS.requireENSOwner(_tokenENS);
_requireMinted(tokenId); _requireMinted(tokenId);
_apps[tokenId].ENS = _tokenENS; _apps[tokenId].ENS = _tokenENS;
emit MetadataUpdate(tokenId, "ENS", _tokenENS, msg.sender); emit MetadataUpdate(tokenId, "ENS", _tokenENS, msg.sender);

View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import {Resolver} from "@ensdomains/ens-contracts/contracts/resolvers/Resolver.sol";
error MustBeENSOwner();
library FleekENS {
ENS internal constant _ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);
/**
* @dev Reverts if the sender is not the owner of the ENS node.
*/
function requireENSOwner(string calldata name) internal view {
if (_ens.owner(namehash(bytes(name), 0)) != msg.sender) revert MustBeENSOwner();
}
/**
* @dev Processes the name and returns the ENS node hash.
*/
function namehash(bytes calldata name, uint256 index) internal view returns (bytes32) {
for (uint256 i = index; i < name.length; i++) {
if (name[i] == ".") {
return keccak256(abi.encodePacked(namehash(name, i + 1), keccak256(name[index:i])));
}
}
return keccak256(abi.encodePacked(bytes32(0x0), keccak256(name[index:name.length])));
}
}

View File

@ -4,3 +4,8 @@ out = 'out'
libs = ['node_modules', 'lib'] libs = ['node_modules', 'lib']
test = 'test/foundry' test = 'test/foundry'
cache_path = 'forge-cache' cache_path = 'forge-cache'
via_ir = true
[rpc_endpoints]
mainnet = "${MAINNET_API_KEY}"

View File

@ -18,6 +18,8 @@ const {
PRIVATE_KEY, PRIVATE_KEY,
REPORT_GAS, REPORT_GAS,
POLYGONSCAN_KEY, POLYGONSCAN_KEY,
MAINNET_API_KEY,
COINMARKETCAP_KEY,
} = process.env; } = process.env;
const config: HardhatUserConfig = { const config: HardhatUserConfig = {
@ -25,6 +27,12 @@ const config: HardhatUserConfig = {
networks: { networks: {
hardhat: { hardhat: {
chainId: 31337, chainId: 31337,
forking: MAINNET_API_KEY
? {
url: MAINNET_API_KEY,
blockNumber: 16876149,
}
: undefined,
}, },
mumbai: { mumbai: {
url: API_URL, url: API_URL,
@ -35,9 +43,9 @@ const config: HardhatUserConfig = {
gasReporter: { gasReporter: {
enabled: REPORT_GAS === 'true' || false, enabled: REPORT_GAS === 'true' || false,
currency: 'USD', currency: 'USD',
outputFile: 'gas-report.txt', outputFile: 'gas-report',
noColors: true, noColors: true,
// coinmarketcap: process.env.COINMARKETCAP_API_KEY, coinmarketcap: COINMARKETCAP_KEY,
}, },
contractSizer: { contractSizer: {
runOnCompile: false, runOnCompile: false,

View File

@ -4,8 +4,8 @@
"description": "", "description": "",
"private": "false", "private": "false",
"scripts": { "scripts": {
"test": "hardhat test && forge test --via-ir", "test": "yarn test:hardhat && yarn test:foundry",
"test:foundry": "forge test --via-ir -vvv", "test:foundry": "forge test -vvv --fork-url mainnet --fork-block-number 16876149",
"test:hardhat": "hardhat test", "test:hardhat": "hardhat test",
"format": "prettier --write \"./**/*.{js,json,sol,ts}\"", "format": "prettier --write \"./**/*.{js,json,sol,ts}\"",
"node:hardhat": "hardhat node", "node:hardhat": "hardhat node",
@ -25,6 +25,8 @@
}, },
"homepage": "https://github.com/fleekxyz/non-fungible-apps#readme", "homepage": "https://github.com/fleekxyz/non-fungible-apps#readme",
"devDependencies": { "devDependencies": {
"@ensdomains/ens-contracts": "^0.0.20",
"@ensdomains/eth-ens-namehash": "^2.0.15",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.5", "@nomicfoundation/hardhat-chai-matchers": "^1.0.5",
"@nomicfoundation/hardhat-network-helpers": "^1.0.7", "@nomicfoundation/hardhat-network-helpers": "^1.0.7",
"@nomicfoundation/hardhat-toolbox": "^2.0.0", "@nomicfoundation/hardhat-toolbox": "^2.0.0",

View File

@ -162,6 +162,7 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7
function test_mint() public { function test_mint() public {
// Anyone can mint // Anyone can mint
transferENS(TestConstants.APP_ENS, anyAddress);
vm.startPrank(anyAddress); vm.startPrank(anyAddress);
mintDefault(address(99)); mintDefault(address(99));
vm.stopPrank(); vm.stopPrank();
@ -201,7 +202,7 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7
} }
function test_setTokenENS() public { function test_setTokenENS() public {
string memory ens = "ens"; string memory ens = "ens.eth";
// ColletionOwner // ColletionOwner
vm.prank(collectionOwner); vm.prank(collectionOwner);
@ -214,10 +215,12 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7
CuT.setTokenENS(tokenId, ens); CuT.setTokenENS(tokenId, ens);
// TokenOwner // TokenOwner
transferENS(ens, tokenOwner);
vm.prank(tokenOwner); vm.prank(tokenOwner);
CuT.setTokenENS(tokenId, ens); CuT.setTokenENS(tokenId, ens);
// TokenController // TokenController
transferENS(ens, tokenController);
vm.prank(tokenController); vm.prank(tokenController);
CuT.setTokenENS(tokenId, ens); CuT.setTokenENS(tokenId, ens);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./TestBase.sol";
import {Utils} from "./Utils.sol";
contract Test_FleekERC721_ENS is Test_FleekERC721_Base {
function expectRevertWithMustBeENSOwner() internal {
vm.expectRevert(MustBeENSOwner.selector);
}
function setUp() public {
baseSetUp();
}
function testFuzz_cannotMintIfNotENSOwner(address account) public {
vm.assume(deployer != account);
vm.prank(account);
expectRevertWithMustBeENSOwner();
mintDefault(account);
}
function testFuzz_cannotSetTokenENSIfNotENSOwner(address account) public {
vm.assume(deployer != account);
mintDefault(account);
vm.prank(account);
expectRevertWithMustBeENSOwner();
CuT.setTokenENS(0, TestConstants.APP_ENS);
}
}

View File

@ -18,7 +18,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
string memory name, string memory name,
string memory description, string memory description,
string memory externalURL, string memory externalURL,
string memory ENS, string memory ens,
uint256 currentBuild, uint256 currentBuild,
string memory logo, string memory logo,
uint24 color uint24 color
@ -28,7 +28,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
assertEq(externalURL, TestConstants.APP_EXTERNAL_URL); assertEq(externalURL, TestConstants.APP_EXTERNAL_URL);
assertEq(logo, TestConstants.LOGO_0); assertEq(logo, TestConstants.LOGO_0);
assertEq(color, TestConstants.APP_COLOR); assertEq(color, TestConstants.APP_COLOR);
assertEq(ENS, TestConstants.APP_ENS); assertEq(ens, TestConstants.APP_ENS);
assertEq(currentBuild, 0); assertEq(currentBuild, 0);
} }
@ -45,6 +45,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
CuT.setTokenName(tokenId, newAppName); CuT.setTokenName(tokenId, newAppName);
CuT.setTokenDescription(tokenId, newDescription); CuT.setTokenDescription(tokenId, newDescription);
CuT.setTokenExternalURL(tokenId, newExternalURL); CuT.setTokenExternalURL(tokenId, newExternalURL);
transferENS(newENS, deployer);
CuT.setTokenENS(tokenId, newENS); CuT.setTokenENS(tokenId, newENS);
CuT.setTokenBuild(tokenId, newCommitHash, newRepository); CuT.setTokenBuild(tokenId, newCommitHash, newRepository);
CuT.setTokenLogoAndColor(tokenId, newLogo, newColor); CuT.setTokenLogoAndColor(tokenId, newLogo, newColor);
@ -53,7 +54,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
string memory name, string memory name,
string memory description, string memory description,
string memory externalURL, string memory externalURL,
string memory ENS, string memory ens,
uint256 currentBuild, uint256 currentBuild,
string memory logo, string memory logo,
uint24 color uint24 color
@ -63,7 +64,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
assertEq(externalURL, newExternalURL); assertEq(externalURL, newExternalURL);
assertEq(logo, newLogo); assertEq(logo, newLogo);
assertEq(color, newColor); assertEq(color, newColor);
assertEq(ENS, newENS); assertEq(ens, newENS);
assertEq(currentBuild, 1); assertEq(currentBuild, 1);
} }

View File

@ -26,6 +26,8 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
function test_mintTwoTokensForTwoAddresses() public { function test_mintTwoTokensForTwoAddresses() public {
uint256 firstMint = mintDefault(deployer); uint256 firstMint = mintDefault(deployer);
transferENS("fleek.eth", deployer);
uint256 secondMint = CuT.mint( uint256 secondMint = CuT.mint(
address(12), address(12),
"Different App Name", "Different App Name",
@ -45,6 +47,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
} }
function test_mintWithAutoApprovalAPsOn() public { function test_mintWithAutoApprovalAPsOn() public {
transferENS("fleek.eth", deployer);
uint256 mint = CuT.mint( uint256 mint = CuT.mint(
address(12), address(12),
"Different App Name", "Different App Name",
@ -83,6 +86,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
bool autoApprovalAp bool autoApprovalAp
) public { ) public {
vm.assume(to != address(0)); vm.assume(to != address(0));
transferENS(ens, deployer);
uint256 tokenId = CuT.mint( uint256 tokenId = CuT.mint(
to, to,
appName, appName,

View File

@ -5,6 +5,7 @@ pragma solidity ^0.8.17;
import "forge-std/Test.sol"; import "forge-std/Test.sol";
import "contracts/FleekERC721.sol"; import "contracts/FleekERC721.sol";
import {TestConstants} from "./Constants.sol"; import {TestConstants} from "./Constants.sol";
import {Utils} from "./Utils.sol";
abstract contract Test_FleekERC721_Assertions is Test { abstract contract Test_FleekERC721_Assertions is Test {
function expectRevertWithTokenRole(uint256 tokenId, FleekAccessControl.TokenRoles role) public { function expectRevertWithTokenRole(uint256 tokenId, FleekAccessControl.TokenRoles role) public {
@ -47,6 +48,7 @@ abstract contract Test_FleekERC721_Assertions is Test {
abstract contract Test_FleekERC721_Base is Test, Test_FleekERC721_Assertions { abstract contract Test_FleekERC721_Base is Test, Test_FleekERC721_Assertions {
FleekERC721 internal CuT; // Contract Under Test FleekERC721 internal CuT; // Contract Under Test
address internal deployer; address internal deployer;
ENS internal constant _ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);
function deployUninitialized() internal returns (FleekERC721) { function deployUninitialized() internal returns (FleekERC721) {
FleekERC721 _contract = new FleekERC721(); FleekERC721 _contract = new FleekERC721();
@ -59,6 +61,15 @@ abstract contract Test_FleekERC721_Base is Test, Test_FleekERC721_Assertions {
CuT = deployUninitialized(); CuT = deployUninitialized();
CuT.initialize("Test Contract", "FLKAPS", new uint256[](0)); CuT.initialize("Test Contract", "FLKAPS", new uint256[](0));
deployer = address(this); deployer = address(this);
transferENS(TestConstants.APP_ENS, deployer);
}
function transferENS(string memory ens, address newOwner) public {
bytes32 node = Utils.namehash(ens);
address ensOwner = _ens.owner(node);
vm.deal(ensOwner, 100000000000);
vm.prank(ensOwner);
_ens.setOwner(node, newOwner);
} }
function mintDefault(address to) internal returns (uint256) { function mintDefault(address to) internal returns (uint256) {

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import {FleekENS} from "contracts/util/FleekENS.sol";
library Utils {
/**
* @dev This function is copyed from `FleekENS.sol`.
* It changes the `internal` modifier to `public` allowing it
* to be used in tests applying memory values
*/
function namehash(string calldata name) public view returns (bytes32) {
return FleekENS.namehash(bytes(name), 0);
}
}

View File

@ -0,0 +1,56 @@
import { expect } from 'chai';
import { TestConstants, Fixtures, Errors, transferENSNode } from './helpers';
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
const { MintParams } = TestConstants;
describe('FleekERC721.ENS', () => {
let fixture: Awaited<ReturnType<typeof Fixtures.default>>;
beforeEach(async () => {
fixture = await loadFixture(Fixtures.default);
});
it('should not allow mint if not ENS owner', async () => {
const { contract, owner } = fixture;
await expect(
contract.mint(
owner.address,
MintParams.name,
MintParams.description,
MintParams.externalUrl,
'app.eth',
MintParams.commitHash,
MintParams.gitRepository,
MintParams.logo,
MintParams.color,
MintParams.accessPointAutoApprovalSettings,
owner.address
)
).to.be.revertedWithCustomError(contract, Errors.MustBeENSOwner);
});
it('should not allow set ENS if not ENS owner', async () => {
const { contract, owner } = fixture;
await transferENSNode('app.eth', owner);
await contract.mint(
owner.address,
MintParams.name,
MintParams.description,
MintParams.externalUrl,
'app.eth',
MintParams.commitHash,
MintParams.gitRepository,
MintParams.logo,
MintParams.color,
MintParams.accessPointAutoApprovalSettings,
owner.address
);
await expect(
contract.setTokenENS(0, 'subdomain.app.eth')
).to.be.revertedWithCustomError(contract, Errors.MustBeENSOwner);
});
});

View File

@ -15,4 +15,5 @@ export const Errors = Object.freeze({
PausableIsSetTo: 'PausableIsSetTo', PausableIsSetTo: 'PausableIsSetTo',
ThereIsNoTokenMinted: 'ThereIsNoTokenMinted', ThereIsNoTokenMinted: 'ThereIsNoTokenMinted',
RequiredPayment: 'RequiredPayment', RequiredPayment: 'RequiredPayment',
MustBeENSOwner: 'MustBeENSOwner',
}); });

View File

@ -1,11 +1,14 @@
import { ethers, upgrades } from 'hardhat'; import { ethers, upgrades } from 'hardhat';
import { TestConstants } from './constants'; import { TestConstants } from './constants';
import { transferENSNode } from './utils';
export abstract class Fixtures { export abstract class Fixtures {
static async default() { static async default() {
// Contracts are deployed using the first signer/account by default // Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners(); const [owner, otherAccount] = await ethers.getSigners();
await transferENSNode(TestConstants.MintParams.ens, owner);
const libraries = { const libraries = {
FleekSVG: (await (await ethers.getContractFactory('FleekSVG')).deploy()) FleekSVG: (await (await ethers.getContractFactory('FleekSVG')).deploy())
.address, .address,

View File

@ -1,3 +1,10 @@
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { ethers, upgrades } from 'hardhat';
import { TestConstants } from './constants';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const namehash = require('@ensdomains/eth-ens-namehash');
export const parseTokenURI = (tokenURI: string) => { export const parseTokenURI = (tokenURI: string) => {
const tokenURIDecoded = Buffer.from( const tokenURIDecoded = Buffer.from(
tokenURI.replace('data:application/json;base64,', ''), tokenURI.replace('data:application/json;base64,', ''),
@ -6,3 +13,25 @@ export const parseTokenURI = (tokenURI: string) => {
return JSON.parse(tokenURIDecoded); return JSON.parse(tokenURIDecoded);
}; };
export const getENSNode = (name: string) => {
return namehash.hash(namehash.normalize(name));
};
export const transferENSNode = async (name: string, to: SignerWithAddress) => {
const ens = await ethers.getContractAt(
'ENS',
'0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'
);
const ensNode = getENSNode(name);
const ensOwner = await ethers.getImpersonatedSigner(await ens.owner(ensNode));
await to.sendTransaction({
to: ensOwner.address,
value: ethers.utils.parseEther('1000'),
});
await ens.connect(ensOwner).setOwner(ensNode, to.address);
};

View File

@ -1,6 +1,6 @@
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { expect } from 'chai'; import { expect } from 'chai';
import { TestConstants, Fixtures, Events } from './helpers'; import { TestConstants, Fixtures, Events, transferENSNode } from './helpers';
const { const {
Logos: { 1: Logo1 }, Logos: { 1: Logo1 },
@ -25,9 +25,11 @@ describe('FleekERC721.UpdateProperties', () => {
it('should emit event for ens change', async () => { it('should emit event for ens change', async () => {
const { contract, tokenId, owner } = fixture; const { contract, tokenId, owner } = fixture;
await expect(contract.setTokenENS(tokenId, 'app.eth')) await transferENSNode('subdomain.app.eth', owner);
await expect(contract.setTokenENS(tokenId, 'subdomain.app.eth'))
.to.emit(contract, Events.MetadataUpdate.string) .to.emit(contract, Events.MetadataUpdate.string)
.withArgs(tokenId, 'ENS', 'app.eth', owner.address); .withArgs(tokenId, 'ENS', 'subdomain.app.eth', owner.address);
}); });
it('should emit event for name change', async () => { it('should emit event for name change', async () => {

View File

@ -14,6 +14,33 @@
dependencies: dependencies:
"@jridgewell/trace-mapping" "0.3.9" "@jridgewell/trace-mapping" "0.3.9"
"@ensdomains/buffer@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@ensdomains/buffer/-/buffer-0.1.1.tgz#6c275ba7e457e935405b67876f1f0d980c8baa63"
integrity sha512-92SfSiNS8XorgU7OUBHo/i1ZU7JV7iz/6bKuLPNVsMxV79/eI7fJR6jfJJc40zAHjs3ha+Xo965Idomlq3rqnw==
"@ensdomains/ens-contracts@^0.0.20":
version "0.0.20"
resolved "https://registry.yarnpkg.com/@ensdomains/ens-contracts/-/ens-contracts-0.0.20.tgz#346eac70d666a7864142287ce1759b0f44bd8a5e"
integrity sha512-lAHQBVj2WtgbchcrE8ZuFI6DFq+O33wkLAGqsO2gcnn0EUJb65OJIdTqUfvfULKGJjkB2pyHfS/RgMSIW6h1Pw==
dependencies:
"@ensdomains/buffer" "^0.1.1"
"@ensdomains/solsha1" "0.0.3"
"@openzeppelin/contracts" "^4.1.0"
dns-packet "^5.3.0"
"@ensdomains/eth-ens-namehash@^2.0.15":
version "2.0.15"
resolved "https://registry.yarnpkg.com/@ensdomains/eth-ens-namehash/-/eth-ens-namehash-2.0.15.tgz#5e5f2f24ba802aff8bc19edd822c9a11200cdf4a"
integrity sha512-JRDFP6+Hczb1E0/HhIg0PONgBYasfGfDheujmfxaZaAv/NAH4jE6Kf48WbqfRZdxt4IZI3jl3Ri7sZ1nP09lgw==
"@ensdomains/solsha1@0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@ensdomains/solsha1/-/solsha1-0.0.3.tgz#fd479da9d40aadb59ff4fb4ec50632e7d2275a83"
integrity sha512-uhuG5LzRt/UJC0Ux83cE2rCKwSleRePoYdQVcqPN1wyf3/ekMzT/KZUF9+v7/AG5w9jlMLCQkUM50vfjr0Yu9Q==
dependencies:
hash-test-vectors "^1.3.2"
"@ethereumjs/common@2.5.0": "@ethereumjs/common@2.5.0":
version "2.5.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268"
@ -398,6 +425,11 @@
"@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/sourcemap-codec" "^1.4.10"
"@leichtgewicht/ip-codec@^2.0.1":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
"@metamask/eth-sig-util@^4.0.0": "@metamask/eth-sig-util@^4.0.0":
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088"
@ -700,6 +732,11 @@
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a"
integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw== integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw==
"@openzeppelin/contracts@^4.1.0":
version "4.8.2"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.2.tgz#d815ade0027b50beb9bcca67143c6bcc3e3923d6"
integrity sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g==
"@openzeppelin/contracts@^4.7.3": "@openzeppelin/contracts@^4.7.3":
version "4.8.1" version "4.8.1"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.1.tgz#709cfc4bbb3ca9f4460d60101f15dac6b7a2d5e4" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.1.tgz#709cfc4bbb3ca9f4460d60101f15dac6b7a2d5e4"
@ -2155,6 +2192,13 @@ dir-glob@^3.0.1:
dependencies: dependencies:
path-type "^4.0.0" path-type "^4.0.0"
dns-packet@^5.3.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b"
integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==
dependencies:
"@leichtgewicht/ip-codec" "^2.0.1"
dom-walk@^0.1.0: dom-walk@^0.1.0:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
@ -3302,6 +3346,11 @@ hash-base@^3.0.0:
readable-stream "^3.6.0" readable-stream "^3.6.0"
safe-buffer "^5.2.0" safe-buffer "^5.2.0"
hash-test-vectors@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/hash-test-vectors/-/hash-test-vectors-1.3.2.tgz#f050fde1aff46ec28dcf4f70e4e3238cd5000f4c"
integrity sha512-PKd/fitmsrlWGh3OpKbgNLE04ZQZsvs1ZkuLoQpeIKuwx+6CYVNdW6LaPIS1QAdZvV40+skk0w4YomKnViUnvQ==
hash.js@1.1.3: hash.js@1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846"