Skip to content

Commit

Permalink
Create validator for deployed contracts (#247)
Browse files Browse the repository at this point in the history
* create interface

* Update IDeploymentValidator.sol

* add contract and testing

* Update deploymentValidatorTest.ts

* add comments

* more tests, approve separate mappings
  • Loading branch information
smmackey committed Mar 21, 2022
1 parent 022fe0a commit 2c22fff
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 0 deletions.
96 changes: 96 additions & 0 deletions contracts/DeploymentValidator.sol
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./libraries/Authorizable.sol";
import "./interfaces/IDeploymentValidator.sol";

contract DeploymentValidator is IDeploymentValidator, Authorizable {
// a mapping of wrapped position contracts deployed by Element
mapping(address => bool) public wrappedPositions;
// a mapping of pool contracts deployed by Element
mapping(address => bool) public pools;
// a mapping of wrapped position + pool pairs that are deployed by Element
// we keccak256 hash these tuples together to serve as the mapping keys
mapping(bytes32 => bool) public pairs;

/// @notice Constructs this contract and stores needed data
/// @param _owner The contract owner authorized to validate addresses
constructor(address _owner) {
// authorize the owner address to be able to execute the validations
_authorize(_owner);
}

/// @notice adds a wrapped position address to the mapping
/// @param wrappedPosition The wrapped position contract address
function validateWPAddress(address wrappedPosition)
public
override
onlyAuthorized
{
// add address to mapping to indicating it was deployed by Element
wrappedPositions[wrappedPosition] = true;
}

/// @notice adds a wrapped position address to the mapping
/// @param pool the pool contract address
function validatePoolAddress(address pool) public override onlyAuthorized {
// add address to mapping to indicating it was deployed by Element
pools[pool] = true;
}

/// @notice adds a wrapped position + pool pair of addresses to mapping
/// @param wrappedPosition the wrapped position contract address
/// @param pool the pool contract address
function validateAddresses(address wrappedPosition, address pool)
external
override
onlyAuthorized
{
// add to pool validation mapping
validatePoolAddress(pool);
// add to wp validation mapping
validateWPAddress(wrappedPosition);
// hash together the contract addresses
bytes32 data = keccak256(abi.encodePacked(wrappedPosition, pool));
// add the hashed pair into the mapping
pairs[data] = true;
}

/// @notice checks to see if the address has been validated
/// @param wrappedPosition the address to check
/// @return true if validated, false if not
function checkWPValidation(address wrappedPosition)
external
view
override
returns (bool)
{
return wrappedPositions[wrappedPosition];
}

/// @notice checks to see if the address has been validated
/// @param pool the address to check
/// @return true if validated, false if not
function checkPoolValidation(address pool)
external
view
override
returns (bool)
{
return pools[pool];
}

/// @notice checks to see if the pair of addresses have been validated
/// @param wrappedPosition the wrapped position address to check
/// @param pool the pool address to check
/// @return true if validated, false if not
function checkPairValidation(address wrappedPosition, address pool)
external
view
override
returns (bool)
{
bytes32 data = keccak256(abi.encodePacked(wrappedPosition, pool));
return pairs[data];
}
}
22 changes: 22 additions & 0 deletions contracts/interfaces/IDeploymentValidator.sol
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

interface IDeploymentValidator {
function validateWPAddress(address wrappedPosition) external;

function validatePoolAddress(address pool) external;

function validateAddresses(address wrappedPosition, address pool) external;

function checkWPValidation(address wrappedPosition)
external
view
returns (bool);

function checkPoolValidation(address pool) external view returns (bool);

function checkPairValidation(address wrappedPosition, address pool)
external
view
returns (bool);
}
127 changes: 127 additions & 0 deletions test/deploymentValidatorTest.ts
@@ -0,0 +1,127 @@
import { ethers, waffle } from "hardhat";
import { expect } from "chai";
import { DeploymentValidator } from "typechain/DeploymentValidator";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { createSnapshot, restoreSnapshot } from "./helpers/snapshots";
import { boolean } from "hardhat/internal/core/params/argumentTypes";

const { provider } = waffle;

describe("Deployment Validator", () => {
let deploymentValidator: DeploymentValidator;
let signers: SignerWithAddress[];

before(async () => {
await createSnapshot(provider);
signers = await ethers.getSigners();

const deployer = await ethers.getContractFactory(
"DeploymentValidator",
signers[0]
);
deploymentValidator = await deployer.deploy(signers[0].address);
});

after(async () => {
await restoreSnapshot(provider);
});

beforeEach(async () => {
await createSnapshot(provider);
});
afterEach(async () => {
await restoreSnapshot(provider);
});

describe("validate wrapped position addresses", () => {
it("validates wp address correctly", async () => {
const mockWPAddress = "0x814C447a9F58A2b823504Fe2775bA48c843925B6";
await deploymentValidator
.connect(signers[0])
.validateWPAddress(mockWPAddress);
const result = await deploymentValidator
.connect(signers[0])
.checkWPValidation(mockWPAddress);
expect(result).to.be.equal(true);
});
it("validate wp fails for unauthorized owner", async () => {
const mockWPAddress = "0x814C447a9F58A2b823504Fe2775bA48c843925B6";
const tx = deploymentValidator
.connect(signers[1])
.validateWPAddress(mockWPAddress);
await expect(tx).to.be.revertedWith("Sender not Authorized");
});
it("validate wp returns false unregistered address", async () => {
const mockWPAddress = "0x8dc82c95B8901Db35390Aa4096B643d7724F278D";
const result = await deploymentValidator
.connect(signers[0])
.checkWPValidation(mockWPAddress);
expect(result).to.be.equal(false);
});
});
describe("validate pool addresses", () => {
it("validates pool address correctly", async () => {
const mockPoolAddress = "0x5941DB4d6C500C4FFa57c359eE0C55c6b41D0b61";
await deploymentValidator
.connect(signers[0])
.validatePoolAddress(mockPoolAddress);
const result = await deploymentValidator
.connect(signers[0])
.checkPoolValidation(mockPoolAddress);
expect(result).to.be.equal(true);
});
it("validate pool fails for unauthorized owner", async () => {
const mockPoolAddress = "0x814C447a9F58A2b823504Fe2775bA48c843925B6";
const tx = deploymentValidator
.connect(signers[1])
.validatePoolAddress(mockPoolAddress);
await expect(tx).to.be.revertedWith("Sender not Authorized");
});
it("validate pool returns false unregistered address", async () => {
const mockPoolAddress = "0x8dc82c95B8901Db35390Aa4096B643d7724F278D";
const result = await deploymentValidator
.connect(signers[0])
.checkPoolValidation(mockPoolAddress);
expect(result).to.be.equal(false);
});
});
describe("validate wp/pool pair addresses", () => {
it("validates addresses correctly", async () => {
const mockWPAddress = "0x6F643Ba6894D8C50c476A3539e1D1690B2194018";
const mockPoolAddress = "0xB59C7597228fEBccEC3dC0571a7Ee39A26E316B9";
await deploymentValidator
.connect(signers[0])
.validateAddresses(mockWPAddress, mockPoolAddress);
// check pair validation
const result1 = await deploymentValidator
.connect(signers[0])
.checkPairValidation(mockWPAddress, mockPoolAddress);
expect(result1).to.be.equal(true);
// check individual mapping validation
const result2 = await deploymentValidator
.connect(signers[0])
.checkWPValidation(mockWPAddress);
expect(result2).to.be.equal(true);
const result3 = await deploymentValidator
.connect(signers[0])
.checkPoolValidation(mockPoolAddress);
expect(result3).to.be.equal(true);
});
it("validate pool/wp pair fails for unauthorized owner", async () => {
const mockWPAddress = "0x6F643Ba6894D8C50c476A3539e1D1690B2194018";
const mockPoolAddress = "0x814C447a9F58A2b823504Fe2775bA48c843925B6";
const tx = deploymentValidator
.connect(signers[1])
.validateAddresses(mockWPAddress, mockPoolAddress);
await expect(tx).to.be.revertedWith("Sender not Authorized");
});
it("validation returns false unregistered addresses", async () => {
const mockWPAddress = "0xb47E7a1fD90630CfC0868d90Cb8F518578010cFe";
const mockPoolAddress = "0x4294005520c453EB8Fa66F53042cfC79707855c4";
const result = await deploymentValidator
.connect(signers[0])
.checkPairValidation(mockWPAddress, mockPoolAddress);
expect(result).to.be.equal(false);
});
});
});

0 comments on commit 2c22fff

Please sign in to comment.