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

Test/transfer meToken ownership #63

Merged
merged 5 commits into from
Dec 3, 2021
Merged
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
5 changes: 5 additions & 0 deletions contracts/interfaces/IMeTokenRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ interface IMeTokenRegistry {
/// @return TODO
function getOwnerMeToken(address _owner) external view returns (address);

/// @notice TODO
/// @param _oldOwner TODO
/// @return TODO
function getPendingOwner(address _oldOwner) external view returns (address);

/// @notice TODO
/// @param meToken Address of meToken queried
/// @return meToken_ details of the meToken
Expand Down
16 changes: 13 additions & 3 deletions contracts/registries/MeTokenRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,14 @@ contract MeTokenRegistry is Ownable, IMeTokenRegistry {

/// @inheritdoc IMeTokenRegistry
function cancelTransferMeTokenOwnership() external override {
address _meToken = _owners[msg.sender];
require(_meToken != address(0), "meToken does not exist");

require(
_pendingOwners[msg.sender] != address(0),
"transferMeTokenOwnership() not initiated"
);

address _meToken = _owners[msg.sender];
require(_meToken != address(0), "meToken does not exist");

delete _pendingOwners[msg.sender];
emit CancelTransferMeTokenOwnership(msg.sender, _meToken);
}
Expand Down Expand Up @@ -345,6 +345,16 @@ contract MeTokenRegistry is Ownable, IMeTokenRegistry {
return _owners[_owner];
}

/// @inheritdoc IMeTokenRegistry
function getPendingOwner(address _oldOwner)
external
view
override
returns (address)
{
return _pendingOwners[_oldOwner];
}

/// @inheritdoc IMeTokenRegistry
function getDetails(address _meToken)
external
Expand Down
157 changes: 113 additions & 44 deletions test/contracts/registries/MeTokenRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ import {
} from "../../utils/helpers";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { hubSetup } from "../../utils/hubSetup";
import { BigNumber } from "ethers";
import { BigNumber, ContractTransaction } from "ethers";
import { expect } from "chai";

describe("MeTokenRegistry.sol", () => {
let meTokenAddr0: string;
let meTokenAddr1: string;
let tx: ContractTransaction;
let meTokenRegistry: MeTokenRegistry;

let hub: Hub;
Expand Down Expand Up @@ -60,15 +63,13 @@ describe("MeTokenRegistry.sol", () => {
const tx = await meTokenRegistry
.connect(account0)
.subscribe(name, "CARL", hubId, 0);
const meTokenAddr = await meTokenRegistry.getOwnerMeToken(
account0.address
);
meTokenAddr0 = await meTokenRegistry.getOwnerMeToken(account0.address);
/* expect(tx)
.to.emit(meTokenRegistry, "Register")
.withArgs(meTokenAddr, account0.address, name, symbol, hubId); */

// assert token infos
const meToken = await getContractAt<MeToken>("MeToken", meTokenAddr);
const meToken = await getContractAt<MeToken>("MeToken", meTokenAddr0);
expect(await meToken.name()).to.equal(name);
expect(await meToken.symbol()).to.equal(symbol);
expect(await meToken.decimals()).to.equal(18);
Expand Down Expand Up @@ -96,86 +97,154 @@ describe("MeTokenRegistry.sol", () => {
const balVault = await token.balanceOf(hubDetail.vault);
expect(balVault).equal(amount);
// assert token infos
const meTokenAddr = await meTokenRegistry.getOwnerMeToken(
account1.address
);
const meToken = await getContractAt<MeToken>("MeToken", meTokenAddr);
meTokenAddr1 = await meTokenRegistry.getOwnerMeToken(account1.address);
const meToken = await getContractAt<MeToken>("MeToken", meTokenAddr1);
// should be greater than 0

const calculatedRes = calculateTokenReturnedFromZero(
20,
toETHNumber(baseY),
reserveWeight / MAX_WEIGHT
);
console.log(` calculatedRes:${calculatedRes}`);
expect(toETHNumber(await meToken.totalSupply())).to.equal(calculatedRes);
});
});

describe("transferOwnership()", () => {
it("Fails if not owner", async () => {
const meTokenAddr = await meTokenRegistry.getOwnerMeToken(
account1.address
);
describe("transferMeTokenOwnership()", () => {
it("Fails if not a meToken owner", async () => {
await expect(
meTokenRegistry
.connect(account3)
.transferMeTokenOwnership(account2.address)
).to.revertedWith("meToken does not exist");

});
it("Fails if recipient already owns a meToken", async () => {
await expect(
meTokenRegistry.transferMeTokenOwnership(account1.address)
).to.revertedWith("_newOwner already owns a meToken");
});
it("Emits TransferOwnership()", async () => {
const meTokenAddr = await meTokenRegistry.getOwnerMeToken(
account1.address
it("Fails if _newOwner is address(0)", async () => {
await expect(
meTokenRegistry.transferMeTokenOwnership(ethers.constants.AddressZero)
).to.be.revertedWith("Cannot transfer to 0 address");
});
it("Successfully queues a recipient to claim ownership", async () => {
expect(await meTokenRegistry.getPendingOwner(account1.address)).to.equal(
ethers.constants.AddressZero
);
const tx = await meTokenRegistry
tx = await meTokenRegistry
.connect(account1)
.transferMeTokenOwnership(account2.address);
const meTokenAddrAfter = await meTokenRegistry.getOwnerMeToken(
account1.address
expect(await meTokenRegistry.getPendingOwner(account1.address)).to.equal(
account2.address
);
await expect(tx)
});
it("Emits TransferOwnership()", async () => {
expect(tx)
.to.emit(meTokenRegistry, "TransferMeTokenOwnership")
.withArgs(account1.address, account2.address, meTokenAddr);
.withArgs(account1.address, account2.address, meTokenAddr1);
});
});

describe("isOwner()", () => {
it("Returns false for address(0)", async () => {
expect(await meTokenRegistry.isOwner(ethers.constants.AddressZero)).to.be
.false;
describe("cancelTransferMeTokenOwnership()", () => {
it("Fails if owner has never called transferMeTokenOwnership()", async () => {
await expect(
meTokenRegistry.connect(account0).cancelTransferMeTokenOwnership()
).to.be.revertedWith("transferMeTokenOwnership() not initiated");
});
it("Revert if ownership is not claimed", async () => {
expect(await meTokenRegistry.isOwner(account2.address)).to.be.false;
it("Fails if owner does not own a meToken", async () => {
await expect(
meTokenRegistry.connect(account2).cancelTransferMeTokenOwnership()
).to.be.revertedWith("meToken does not exist");
});
it("Claim ownership should work", async () => {
const meTokenAddr = await meTokenRegistry.getOwnerMeToken(
account1.address
it("Succesfully cancels transfer and removes from _pendingOwners", async () => {
tx = await meTokenRegistry
.connect(account1)
.cancelTransferMeTokenOwnership();
expect(await meTokenRegistry.getPendingOwner(account1.address)).to.equal(
ethers.constants.AddressZero
);
const tx = await meTokenRegistry
});
it("Emits CancelTransferMeTokenOwnership()", async () => {
expect(tx)
.to.emit(meTokenRegistry, "CancelTransferMeTokenOwnership")
.withArgs(account1.address, meTokenAddr1);
});
});

describe("claimMeTokenOwnership()", () => {
it("Fails if claimer already owns a meToken", async () => {
// scenario 1: already owns a meToken, not a pending owner
await expect(
meTokenRegistry
.connect(account0)
.claimMeTokenOwnership(ethers.constants.AddressZero)
).to.be.revertedWith("Already owns a meToken");
// Scenario 2: doesn't own a meToken and becomes pending owner for 2 meTokens,
// claims ownership to the first, then tries claiming ownership to the second
await meTokenRegistry
.connect(account0)
.transferMeTokenOwnership(account2.address);
await meTokenRegistry
.connect(account1)
.transferMeTokenOwnership(account2.address);
tx = await meTokenRegistry
.connect(account2)
.claimMeTokenOwnership(account1.address);
const meTokenAddrAfter = await meTokenRegistry.getOwnerMeToken(
account2.address
.claimMeTokenOwnership(account0.address);
await expect(
meTokenRegistry
.connect(account2)
.claimMeTokenOwnership(account1.address)
).to.be.revertedWith("Already owns a meToken");
});
it("Fails if not claimer not pending owner from oldOwner", async () => {
await expect(
meTokenRegistry
.connect(account3)
.claimMeTokenOwnership(account1.address)
).to.be.revertedWith("!_pendingOwner");
});
it("Successfully completes claim and updates meToken struct, deletes old mappings", async () => {
expect(await meTokenRegistry.getOwnerMeToken(account2.address)).to.equal(
meTokenAddr0
);
const details = await meTokenRegistry.getDetails(meTokenAddr0);
expect(details.owner).to.equal(account2.address);
expect(await meTokenRegistry.getPendingOwner(account0.address)).to.equal(
ethers.constants.AddressZero
);
expect(meTokenAddr).to.equal(meTokenAddrAfter);
await expect(tx)
expect(await meTokenRegistry.getOwnerMeToken(account0.address)).to.equal(
ethers.constants.AddressZero
);
});
it("Emits ClaimMeTokenOwnership()", async () => {
expect(tx)
.to.emit(meTokenRegistry, "ClaimMeTokenOwnership")
.withArgs(account1.address, account2.address, meTokenAddr);
.withArgs(account0.address, account2.address, meTokenAddr0);
});
});

describe("isOwner()", () => {
it("Returns false for address(0)", async () => {
expect(await meTokenRegistry.isOwner(ethers.constants.AddressZero)).to.be
.false;
});
it("Returns false for if address not an owner", async () => {
expect(await meTokenRegistry.isOwner(account3.address)).to.be.false;
});
it("Returns true for a meToken issuer", async () => {
expect(await meTokenRegistry.isOwner(account2.address)).to.be.true;
expect(await meTokenRegistry.isOwner(account1.address)).to.be.true;
});
});
describe("balancePool", () => {
it("Fails if not foundry", async () => {
const meTokenAddr = await meTokenRegistry.getOwnerMeToken(
account1.address
);
await expect(
meTokenRegistry.updateBalancePooled(true, meTokenAddr, account2.address)
meTokenRegistry.updateBalancePooled(
true,
meTokenAddr1,
account2.address
)
).to.revertedWith("!foundry");
});
it("updateBalancePooled()", async () => {
Expand Down