Skip to content

Commit

Permalink
feat: add boolean to toggle migration
Browse files Browse the repository at this point in the history
  • Loading branch information
JGcarv committed Jun 5, 2024
1 parent 17470e7 commit 9cee032
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 14 deletions.
22 changes: 19 additions & 3 deletions contracts/Migrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ pragma solidity 0.8.7;

import { ERC20Helper } from "../modules/erc20-helper/src/ERC20Helper.sol";

import { IERC20Like } from "./interfaces/Interfaces.sol";
import { IERC20Like, IGlobalsLike } from "./interfaces/Interfaces.sol";

import { IMigrator } from "./interfaces/IMigrator.sol";

contract Migrator is IMigrator {

uint256 public immutable override TOKEN_SPLIT_SCALAR;

address public immutable override globals;
address public immutable override newToken;
address public immutable override oldToken;

constructor(address oldToken_, address newToken_, uint256 scalar_) {
bool public override active;

constructor(address globals_, address oldToken_, address newToken_, uint256 scalar_) {
require(IERC20Like(newToken_).decimals() == IERC20Like(oldToken_).decimals(), "M:C:DECIMAL_MISMATCH");

globals = globals_;

oldToken = oldToken_;
newToken = newToken_;

Expand All @@ -28,10 +33,21 @@ contract Migrator is IMigrator {
}

function migrate(address owner_, uint256 amount_) public override {
require(amount_ != uint256(0), "M:M:ZERO_AMOUNT");
require(active, "M:M:INACTIVE");
require(amount_ != uint256(0), "M:M:ZERO_AMOUNT");

require(ERC20Helper.transferFrom(oldToken, owner_, address(this), amount_), "M:M:TRANSFER_FROM_FAILED");
require(ERC20Helper.transfer(newToken, owner_, amount_ * TOKEN_SPLIT_SCALAR), "M:M:TRANSFER_FAILED");
}

function setActive(bool active_) external {
require(
msg.sender == IGlobalsLike(globals).governor() ||
msg.sender == IGlobalsLike(globals).operationalAdmin(),
"M:SA:NOT_PROTOCOL_ADMIN"
);

active = active_;
}

}
12 changes: 12 additions & 0 deletions contracts/interfaces/IMigrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ pragma solidity ^0.8.7;

interface IMigrator {

/**
* @dev Get the status of the migrator.
* @return active_ True if migrations are active.
*/
function active() external view returns (bool active_);

/**
* @dev Gets the Maple Globals address
* @param globals_ The address of the Maple globals.
*/
function globals() external view returns (address globals_);

/**
* @dev Get address of newToken.
* @return newToken_ The address of new token.
Expand Down
8 changes: 8 additions & 0 deletions contracts/interfaces/Interfaces.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ interface IERC20Like {
function decimals() external view returns (uint8 decimals_);

}

interface IGlobalsLike {

function governor() external view returns (address governor_);

function operationalAdmin() external view returns (address operationalAdmin_);

}
114 changes: 103 additions & 11 deletions tests/Migrator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,119 @@ import { MockERC20 } from "../modules/erc20/contracts/test/mocks/MockERC20.sol";

import { Migrator } from "../contracts/Migrator.sol";

import { MockGlobals } from "./mocks/Mocks.sol";

contract MigratorConstructorTest is Test {

function test_constructor_mismatch_decimals() external {
MockGlobals globals = new MockGlobals();
MockERC20 oldToken = new MockERC20("Old Token", "OT", 18);
MockERC20 newToken = new MockERC20("New Token", "NT", 17);

vm.expectRevert("M:C:DECIMAL_MISMATCH");
new Migrator(address(oldToken), address(newToken), 1);
new Migrator(address(globals), address(oldToken), address(newToken), 1);
}

function test_constructor() external {
MockERC20 oldToken = new MockERC20("Old Token", "OT", 18);
MockERC20 newToken = new MockERC20("New Token", "NT", 18);
MockGlobals globals = new MockGlobals();
MockERC20 oldToken = new MockERC20("Old Token", "OT", 18);
MockERC20 newToken = new MockERC20("New Token", "NT", 18);

Migrator migrator = new Migrator(address(oldToken), address(newToken), 1);
Migrator migrator = new Migrator(address(globals), address(oldToken), address(newToken), 1);

assertEq(migrator.globals(), address(globals));
assertEq(migrator.oldToken(), address(oldToken));
assertEq(migrator.newToken(), address(newToken));
}

}

contract SetActiveTests is Test {

uint256 internal constant SCALAR = 10;
uint256 internal constant OLD_SUPPLY = 10_000_000 ether;

address operationalAdmin = makeAddr("operationalAdmin");
address governor = makeAddr("governor");
address account = makeAddr("account");

Migrator internal _migrator;
MockERC20 internal _oldToken;
MockERC20 internal _newToken;
MockGlobals internal _globals;

function setUp() external {
_globals = new MockGlobals();

_globals.__setGovernor(governor);
_globals.__setOperationalAdmin(operationalAdmin);

_oldToken = new MockERC20("Old Token", "OT", 18);
_newToken = new MockERC20("New Token", "NT", 18);

_migrator = new Migrator(address(_globals), address(_oldToken), address(_newToken), SCALAR);
}

function test_setActive_notProtocolAdmin() external {
vm.expectRevert("M:SA:NOT_PROTOCOL_ADMIN");
_migrator.setActive(false);
}

function test_setActive_withGovernor() external {
assertEq(_migrator.active(), false);

vm.prank(governor);
_migrator.setActive(true);

assertEq(_migrator.active(), true);

vm.prank(governor);
_migrator.setActive(false);

assertEq(_migrator.active(), false);
}

function test_setActive_withOperationalAdmin() external {
assertEq(_migrator.active(), false);

vm.prank(operationalAdmin);
_migrator.setActive(true);

assertEq(_migrator.active(), true);

vm.prank(operationalAdmin);
_migrator.setActive(false);

assertEq(_migrator.active(), false);
}

}

contract MigratorTest is Test {

uint256 internal constant SCALAR = 10;
uint256 internal constant OLD_SUPPLY = 10_000_000 ether;

address account = makeAddr("account");
address operationalAdmin = makeAddr("operationalAdmin");
address account = makeAddr("account");

Migrator internal _migrator;
MockERC20 internal _oldToken;
MockERC20 internal _newToken;
Migrator internal _migrator;
MockERC20 internal _oldToken;
MockERC20 internal _newToken;
MockGlobals internal _globals;

function setUp() external {
_globals = new MockGlobals();

_oldToken = new MockERC20("Old Token", "OT", 18);
_newToken = new MockERC20("New Token", "NT", 18);

_migrator = new Migrator(address(_oldToken), address(_newToken), SCALAR);
_migrator = new Migrator(address(_globals), address(_oldToken), address(_newToken), SCALAR);

_globals.__setOperationalAdmin(operationalAdmin);

vm.prank(operationalAdmin);
_migrator.setActive(true);

// Mint new token to migrator
_newToken.mint(address(_migrator), OLD_SUPPLY * SCALAR);
Expand All @@ -69,6 +144,14 @@ contract MigratorTest is Test {
assertEq(_newToken.balanceOf(address(_migrator)), (OLD_SUPPLY * SCALAR)- newAmount);
}

function test_migrate_inactive() external {
vm.prank(operationalAdmin);
_migrator.setActive(false);

vm.expectRevert("M:M:INACTIVE");
_migrator.migrate(1);
}

function testFuzz_migrate_insufficientApproval(uint256 amount_) external {
amount_ = bound(amount_, 1, OLD_SUPPLY);

Expand Down Expand Up @@ -255,15 +338,21 @@ contract TokenSplitScalars is Test {

uint256 internal constant OLD_SUPPLY = 10_000_000 ether;

address account = makeAddr("account");
address operationalAdmin = makeAddr("operationalAdmin");
address account = makeAddr("account");

Migrator internal _migrator;
MockERC20 internal _oldToken;
MockERC20 internal _newToken;
MockGlobals internal _globals;

function setUp() external {
_globals = new MockGlobals();

_oldToken = new MockERC20("Old Token", "OT", 18);
_newToken = new MockERC20("New Token", "NT", 18);

_globals.__setOperationalAdmin(operationalAdmin);
}

function testFuzz_tokenSplitScalar(uint256 amount_, uint16 scalar_) external {
Expand All @@ -273,7 +362,10 @@ contract TokenSplitScalars is Test {

uint256 newAmount = amount_ * scalar_;

_migrator = new Migrator(address(_oldToken), address(_newToken), scalar_);
_migrator = new Migrator(address(_globals), address(_oldToken), address(_newToken), scalar_);

vm.prank(operationalAdmin);
_migrator.setActive(true);

_newToken.mint(address(_migrator), OLD_SUPPLY * scalar_);

Expand Down
17 changes: 17 additions & 0 deletions tests/mocks/Mocks.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.7;

contract MockGlobals {

address public governor;
address public operationalAdmin;

function __setGovernor(address governor_) external {
governor = governor_;
}

function __setOperationalAdmin(address operationalAdmin_) external {
operationalAdmin = operationalAdmin_;
}

}

0 comments on commit 9cee032

Please sign in to comment.