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

Feature/add ve fee distributor owner #746

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
74 changes: 74 additions & 0 deletions contracts/ve/veFeeDistributorOwner.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// BigchainDB GmbH and Ocean Protocol contributors
// SPDX-License-Identifier: (Apache-2.0 AND MIT)

pragma solidity 0.8.12;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";


interface IveFeeDistributor{
function token() external view returns(address);
function checkpoint_token() external;
function checkpoint_total_supply() external;
function commit_admin(address) external;
function apply_admin() external;
function toggle_allow_checkpoint_token() external;
function kill_me() external;
function recover_balance(address) external;
}

contract veFeeDistributorOwner is Ownable{
address public immutable veFeeDistributorToken;
address public immutable veFeeDistributorContract;

event CommitAdmin(address admin);
event ApplyAdmin(address admin);
event ToggleAllowCheckpointToken(bool toogle_flag);
event CheckpointToken(uint256 time,uint256 tokens);

constructor(
address _veFeeDistributor
) payable {
require(
_veFeeDistributor != address(0),
"_veFeeDistributor is zero address"
);
veFeeDistributorContract=_veFeeDistributor;
veFeeDistributorToken=IveFeeDistributor(_veFeeDistributor).token();
require(
veFeeDistributorToken != address(0),
"_veFeeDistributor token is zero address"
);
}

function checkpoint_token() external{
IveFeeDistributor(veFeeDistributorContract).checkpoint_token();
}
function checkpoint_total_supply() external{
IveFeeDistributor(veFeeDistributorContract).checkpoint_total_supply();
}
function checkpoint() external{
IveFeeDistributor(veFeeDistributorContract).checkpoint_token();
IveFeeDistributor(veFeeDistributorContract).checkpoint_total_supply();
}
function commit_admin(address admin) external onlyOwner{
IveFeeDistributor(veFeeDistributorContract).commit_admin(admin);
}
function apply_admin() external onlyOwner{
IveFeeDistributor(veFeeDistributorContract).apply_admin();
}
function toggle_allow_checkpoint_token() external onlyOwner{
IveFeeDistributor(veFeeDistributorContract).toggle_allow_checkpoint_token();
}
function kill_me() external onlyOwner{
trizin marked this conversation as resolved.
Show resolved Hide resolved
IveFeeDistributor(veFeeDistributorContract).kill_me();
uint256 balance = IERC20(veFeeDistributorToken).balanceOf(address(this));
SafeERC20.safeTransfer(IERC20(veFeeDistributorToken), owner(), balance);
}
function recover_balance(address token) external onlyOwner{
IveFeeDistributor(veFeeDistributorContract).recover_balance(token);
uint256 balance = IERC20(token).balanceOf(address(this));
SafeERC20.safeTransfer(IERC20(token), owner(), balance);
}
}
141 changes: 141 additions & 0 deletions test/unit/ve/veFeeOwner.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/* eslint-env mocha */
/* global artifacts, contract, web3, it, beforeEach */
const hre = require("hardhat");
const { assert, expect } = require("chai");
const { expectRevert, expectEvent, BN } = require("@openzeppelin/test-helpers");
const { impersonate } = require("../../helpers/impersonate");
const constants = require("../../helpers/constants");
const { web3 } = require("@openzeppelin/test-helpers/src/setup");
const { sha256 } = require("@ethersproject/sha2");
const {getEventFromTx} = require("../../helpers/utils");
const { ZERO_ADDRESS } = require("@openzeppelin/test-helpers/src/constants");
const ethers = hre.ethers;
const { ecsign } = require("ethereumjs-util");


describe("veFeeOwner tests", () => {
let veFeeDistributor,
veFeeDistributorOwner,
veOcean,
oceanToken,
mockERC20Token,
owner,
alice,
bob

it("#deploy veOcean, veFeeDistributor, veFeeOwner & Ocean", async () => {
[owner, alice,bob] = await ethers.getSigners();
const OceanToken = await ethers.getContractFactory('MockOcean');
oceanToken = await OceanToken.connect(owner).deploy(owner.address);
const MockERC20Token = await ethers.getContractFactory('MockERC20');
mockERC20Token = await MockERC20Token.connect(owner).deploy(owner.address,'Mock','Mock');
const VeOcean = await ethers.getContractFactory("veOCEAN");
veOcean = await VeOcean.connect(owner).deploy(oceanToken.address,"veOCEAN", "veOCEAN", "0.1.0");
const VeFeeDistributor = await ethers.getContractFactory("veFeeDistributor");
const timestamp = Math.floor(new Date().getTime() / 1000)
veFeeDistributor = await VeFeeDistributor.connect(owner).deploy(veOcean.address,
1,
oceanToken.address,
owner.address,
owner.address);
await veFeeDistributor.deployed()
const VeFeeDistributorOwner = await ethers.getContractFactory("veFeeDistributorOwner");
veFeeDistributorOwner = await VeFeeDistributorOwner.connect(owner).deploy(veFeeDistributor.address);
await veFeeDistributorOwner.deployed()
await veFeeDistributor.connect(owner).toggle_allow_checkpoint_token()
assert(await veFeeDistributor.can_checkpoint_token()===true)
await oceanToken.transfer(alice.address,1000)
let tx = await oceanToken.transfer(bob.address,1000)
await tx.wait()
const aliceBalance = await oceanToken.balanceOf(alice.address)
assert(String(aliceBalance)==='1000', 'Alice balance is off. Expecting 1000, got '+aliceBalance)
tx = await veFeeDistributor.connect(owner).commit_admin(veFeeDistributorOwner.address)
await tx.wait()
tx = await veFeeDistributor.connect(owner).apply_admin()
await tx.wait()
assert(await veFeeDistributor.admin()==veFeeDistributorOwner.address, 'veFeeDistributor ownership change failed')
const token = await veFeeDistributorOwner.veFeeDistributorToken()
assert(token==oceanToken.address, ' veFeeDistributor token missmatch. Expecting '+oceanToken.address+', got '+token)
const veDistContract = await veFeeDistributorOwner.veFeeDistributorContract()
assert(veDistContract==veFeeDistributor.address, ' veFeeDistributor contract missmatch. Expecting '+veFeeDistributor.address+', got '+token)
const ownerCHeck = await veFeeDistributorOwner.owner()
assert(ownerCHeck===owner.address,"veFeeDistributor owner is wrong")


})
it("#Alice locks OceanTokens", async () => {
//alice locks 1000 ocean
const unlockTime = Math.floor(new Date().getTime() / 1000) + 60*60*24*30
await oceanToken.connect(alice).approve(veOcean.address,1000)
const tx = await veOcean.connect(alice).create_lock(1000,unlockTime)
const txReceipt = await tx.wait();

});
it("#Owner sends 1000 Ocean to feeDistributor", async () => {
const tx = await oceanToken.connect(owner).transfer(veFeeDistributor.address,1000)
await tx.wait()
const veFeeDistributorBalance = await oceanToken.balanceOf(veFeeDistributor.address)
assert(String(veFeeDistributorBalance)==='1000', 'veFeeDistributor balance is off. Expecting 1000, got '+veFeeDistributorBalance)
});
it("#Anyone can checkpoint veFeeDistributor", async () => {
let tx = await veFeeDistributorOwner.connect(alice).checkpoint_token()
let txReceipt = await tx.wait();
let event = getEventFromTx(txReceipt,'CheckpointToken')
assert(event, "Cannot find CheckpointToken event")
tx = await veFeeDistributorOwner.connect(alice).checkpoint_total_supply()
txReceipt = await tx.wait();
tx = await veFeeDistributorOwner.connect(alice).checkpoint()
txReceipt = await tx.wait();
event = getEventFromTx(txReceipt,'CheckpointToken')
assert(event, "Cannot find CheckpointToken event")
})
it("#Alice should fail to call veFeeDistributor checkpoint", async () => {
await expectRevert.unspecified(
veFeeDistributor
.connect(alice)
.checkpoint_token()
);
})
it("#Alice should fail to call veFeeDistributorOwner kill_me", async () => {
await expectRevert.unspecified(
veFeeDistributorOwner
.connect(alice)
.kill_me()
);
await expectRevert.unspecified(
veFeeDistributorOwner
.connect(alice)
.recover_balance(oceanToken.address)
);
await expectRevert.unspecified(
veFeeDistributorOwner
.connect(alice)
.commit_admin(alice.address)
);
await expectRevert.unspecified(
veFeeDistributorOwner
.connect(alice)
.apply_admin()
);
})
it("#Owner should be able to call veFeeDistributorOwner recover_balance", async () => {
await mockERC20Token.connect(owner).transfer(veFeeDistributor.address,100)
let veFeeDistributorBalance = await mockERC20Token.balanceOf(veFeeDistributor.address)
assert(String(veFeeDistributorBalance)==='100', 'veFeeDistributor balance is off. Expecting 100, got '+veFeeDistributorBalance)
await
veFeeDistributorOwner
.connect(owner)
.recover_balance(mockERC20Token.address)
veFeeDistributorBalance = await mockERC20Token.balanceOf(veFeeDistributor.address)
assert(String(veFeeDistributorBalance)==='0', 'veFeeDistributor balance is off. Expecting 0, got '+veFeeDistributorBalance)

})
it("#Owner should be able to tranfer veFeeDistributor ownership to Alice", async () => {
assert(await veFeeDistributor.admin()!=alice.address,' Alice cannot be admin yet')
await veFeeDistributorOwner.connect(owner).commit_admin(alice.address)
const tx = await veFeeDistributorOwner.connect(owner).apply_admin()
await tx.wait()
assert(await veFeeDistributor.admin()===alice.address,' Alice should be the new admin')
})

});