Skip to content

Commit

Permalink
Merge branch 'main' into chore/certora-ci-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
iamsahu authored Nov 5, 2024
2 parents 691b1a2 + a419ced commit c870119
Show file tree
Hide file tree
Showing 11 changed files with 929 additions and 112 deletions.
415 changes: 373 additions & 42 deletions contracts/src/migration/TLC_globalUnlockScheduleMigration.sol

Large diffs are not rendered by default.

138 changes: 138 additions & 0 deletions contracts/test/RedeemManager.2.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.20;

import "forge-std/Test.sol";
import "../src/RedeemManager.1.sol";
import "./mocks/MockERC20.sol";
import "../src/Allowlist.1.sol";

import "./utils/LibImplementationUnbricker.sol";

interface IRedeemManagerV1Mock {
/// @notice Thrown when a transfer error occured with LsETH
error TransferError();
}

contract RedeemManagerV1Mock is RedeemManagerV1 {
// The error we are testing for
function redeem(uint256 _lsETHAmount) external onlyRedeemerOrRiver {
if (!_castedRiver().transferFrom(msg.sender, address(this), _lsETHAmount)) {
revert TransferError();
}
}
}

contract RiverMock is MockERC20 {
mapping(address => uint256) internal balances;
mapping(address => mapping(address => uint256)) internal approvals;
address internal allowlist;
uint256 internal rate = 1e18;
uint256 internal _totalSupply;

constructor(address _allowlist) MockERC20("Mock River", "MRIV", 18) {
allowlist = _allowlist;
}

function approve(address to, uint256 amount) public virtual override returns (bool) {
approvals[msg.sender][to] = amount;
return true;
}

error ApprovedAmountTooLow();

function transferFrom(address from, address to, uint256 amount) public override returns (bool) {
if (transferFromFail) {
return false;
}
if (approvals[from][msg.sender] < amount) {
revert ApprovedAmountTooLow();
}
if (approvals[from][msg.sender] != type(uint256).max) {
approvals[from][msg.sender] -= amount;
}
balances[from] -= amount;
balances[to] += amount;
return true;
}

function balanceOf(address account) public view virtual override returns (uint256) {
return balances[account];
}

/// @notice Sets the balance of the given account and updates totalSupply
/// @param account The account to set the balance of
/// @param amount Amount to set as balance
function sudoDeal(address account, uint256 amount) external {
if (amount > balances[account]) {
_totalSupply += amount - balances[account];
} else {
_totalSupply -= balances[account] - amount;
}
balances[account] = amount;
}

function sudoSetRate(uint256 newRate) external {
rate = newRate;
}

function getAllowlist() external view returns (address) {
return allowlist;
}

function sudoReportWithdraw(address redeemManager, uint256 lsETHAmount) external payable {
RedeemManagerV1(redeemManager).reportWithdraw{value: msg.value}(lsETHAmount);
}

function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}

function totalUnderlyingSupply() external view returns (uint256) {
return (_totalSupply * rate) / 1e18;
}

function underlyingBalanceFromShares(uint256 shares) external view returns (uint256) {
return (shares * rate) / 1e18;
}

function pullExceedingEth(address redeemManager, uint256 amount) external {
RedeemManagerV1(redeemManager).pullExceedingEth(amount);
}

fallback() external payable {}
receive() external payable {}
}

contract RedeemManagerTest is Test {
RedeemManagerV1Mock internal redeemManager;
AllowlistV1 internal allowlist;
RiverMock internal river;
address internal allowlistAdmin;
address internal allowlistAllower;
address internal allowlistDenier;
address public mockRiverAddress;

function setUp() external {
allowlistAdmin = makeAddr("allowlistAdmin");
allowlistAllower = makeAddr("allowlistAllower");
allowlistDenier = makeAddr("allowlistDenier");
redeemManager = new RedeemManagerV1Mock();
LibImplementationUnbricker.unbrick(vm, address(redeemManager));
allowlist = new AllowlistV1();
LibImplementationUnbricker.unbrick(vm, address(allowlist));
allowlist.initAllowlistV1(allowlistAdmin, allowlistAllower);
allowlist.initAllowlistV1_1(allowlistDenier);
river = new RiverMock(address(allowlist));

redeemManager.initializeRedeemManagerV1(address(river));
}

function testTransferError() public {
// make the transferFrom fail
river.setTransferFromFail(true);

vm.expectRevert(IRedeemManagerV1Mock.TransferError.selector);
vm.prank(address(river));
redeemManager.redeem(100 ether);
}
}
192 changes: 134 additions & 58 deletions contracts/test/migration/TLC_globalUnlockScheduleMigration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,132 @@ import "forge-std/Test.sol";

import "../../src/migration/TLC_globalUnlockScheduleMigration.sol";
import "../../src/TLC.1.sol";
import {ERC20VestableVotesUpgradeableV1} from "contracts/src/components/ERC20VestableVotesUpgradeable.1.sol";

contract TlcMigrationTest is Test {
TlcMigration migrationsContract;
TLCV1 tlc;
string rpc;

uint32[] newLockDuration = [
108604800,
108604800,
108604800,
108604800,
108604800,
108604800,
108604800,
103161600,
98323200,
105235200,
105235200,
105235200,
105235200,
99878400,
89337600,
91065600,
90806400,
86572800,
108604800,
82306800,
108604800,
82306800,
108604800,
82306800,
108604800,
108604800,
108604800,
103161600,
83203200,
83203200,
83548800,
83635200,
83721600,
83548800,
83721600,
83721600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
75693600,
73785600,
81561600,
74476800,
79833600,
77846400,
71020800,
75693600,
75693600,
75693600,
63763200,
64972800,
64713600,
69811200,
69897600,
68688000,
67478400,
65059200,
64454400,
64454400,
59356800,
58924800,
58924800,
57801600,
57110400,
54086400,
57196800,
55641600,
52963200,
55641600,
83116800,
83116800,
54172800,
55641600,
74131200,
49939200,
49334400,
47952000,
47952000,
43286400,
42076800,
46915200,
36979200
];

bool[] isGlobalUnlockedScheduleIgnoredOld;

function setUp() public {
rpc = vm.rpcUrl("mainnet");
vm.createFork(rpc);
}

function testCreate() public {
migrationsContract = new TlcMigration();
}

function testGas() public {
vm.createSelectFork(rpc, 18063740);

vm.createSelectFork(rpc, 20934540);
migrationsContract = new TlcMigration();
proxy tlcProxy = proxy(0xb5Fe6946836D687848B5aBd42dAbF531d5819632);
vm.prank(0x0D1dE267015a75F5069fD1c9ed382210B3002cEb);
Expand All @@ -30,14 +139,17 @@ contract TlcMigrationTest is Test {

function testMigrate() public {
// Significantly faster when cached locally, run a local fork for best perf (anvil recommended)
vm.createSelectFork(rpc, 18063740);
vm.createSelectFork(rpc, 20934540);

proxy tlcProxy = proxy(0xb5Fe6946836D687848B5aBd42dAbF531d5819632);
assertEq(tlcProxy.getVestingScheduleCount(), 67);
assertEq(tlcProxy.getVestingScheduleCount(), 103);

VestingSchedulesV2.VestingSchedule[] memory schedulesBefore = new VestingSchedulesV2.VestingSchedule[](67);
for (uint256 i = 0; i < 67; i++) {
VestingSchedulesV2.VestingSchedule[] memory schedulesBefore = new VestingSchedulesV2.VestingSchedule[](103);
for (uint256 i = 0; i < 103; i++) {
schedulesBefore[i] = TLCV1(address(tlcProxy)).getVestingSchedule(i);
isGlobalUnlockedScheduleIgnoredOld.push(
ERC20VestableVotesUpgradeableV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(i)
);
//console.log("%s,%s,%s", i, schedulesBefore[i].start, schedulesBefore[i].end);
}

Expand All @@ -47,69 +159,33 @@ contract TlcMigrationTest is Test {

tlc = new TLCV1();
vm.prank(0x0D1dE267015a75F5069fD1c9ed382210B3002cEb);
tlcProxy.upgradeTo(address(tlc));
tlcProxy.upgradeTo(address(0xF8745c392feF5c91fa1cdB0202efF7Ca08dF55ce));

assertEq(tlcProxy.getVestingScheduleCount(), 67);
assertEq(tlcProxy.getVestingScheduleCount(), 103);

// Check that the all the values that shouldn't change didn't
for (uint256 i = 0; i < 67; i++) {
for (uint256 i = 0; i < tlcProxy.getVestingScheduleCount(); i++) {
VestingSchedulesV2.VestingSchedule memory schedule = TLCV1(address(tlcProxy)).getVestingSchedule(i);
assertEq(schedule.start, schedulesBefore[i].start);
assertEq(schedule.end, schedulesBefore[i].end);
assertEq(schedule.cliffDuration, schedulesBefore[i].cliffDuration);
assertEq(schedule.duration, schedulesBefore[i].duration);
assertEq(schedule.periodDuration, schedulesBefore[i].periodDuration);
assertEq(schedule.amount, schedulesBefore[i].amount);
assertEq(schedule.creator, schedulesBefore[i].creator);
assertEq(schedule.beneficiary, schedulesBefore[i].beneficiary);
assertEq(schedule.revocable, schedulesBefore[i].revocable);
assertEq(schedule.releasedAmount, schedulesBefore[i].releasedAmount);
assertEq(
isGlobalUnlockedScheduleIgnoredOld[i],
ERC20VestableVotesUpgradeableV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(i)
);
}
// Check that the value we should have changed did change
// Schedule 0
VestingSchedulesV2.VestingSchedule memory schedule = TLCV1(address(tlcProxy)).getVestingSchedule(0);
assertEq(schedule.start, schedulesBefore[0].start);
assertEq(schedule.end, schedulesBefore[0].end);
assertEq(schedule.lockDuration, 75772800);
assertEq(schedule.cliffDuration, schedulesBefore[0].cliffDuration);
assertEq(schedule.duration, schedulesBefore[0].duration);
assertEq(schedule.periodDuration, schedulesBefore[0].periodDuration);
assertFalse(TLCV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(0));

// Schedule 17
schedule = TLCV1(address(tlcProxy)).getVestingSchedule(17);
assertEq(schedule.start, schedulesBefore[17].start);
assertEq(schedule.end, schedulesBefore[17].end);
assertEq(schedule.lockDuration, 53740800);
assertEq(schedule.cliffDuration, schedulesBefore[17].cliffDuration);
assertEq(schedule.duration, schedulesBefore[17].duration);
assertEq(schedule.periodDuration, schedulesBefore[17].periodDuration);
assertTrue(TLCV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(17));

// Schedule 36
schedule = TLCV1(address(tlcProxy)).getVestingSchedule(36);
assertEq(schedule.start, 1686175200);
assertEq(schedule.end, 1686261600);
assertEq(schedule.lockDuration, 42861600);
assertEq(schedule.cliffDuration, schedulesBefore[36].cliffDuration);
assertEq(schedule.duration, 86400);
assertEq(schedule.periodDuration, 86400);
assertFalse(TLCV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(36));

// Schedule 60
schedule = TLCV1(address(tlcProxy)).getVestingSchedule(60);
assertEq(schedule.start, 1686175200);
assertEq(schedule.end, 1686261600);
assertEq(schedule.lockDuration, 42861600);
assertEq(schedule.cliffDuration, schedulesBefore[60].cliffDuration);
assertEq(schedule.duration, 86400);
assertEq(schedule.periodDuration, 86400);
assertFalse(TLCV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(60));

// Schedule 66
schedule = TLCV1(address(tlcProxy)).getVestingSchedule(66);
assertEq(schedule.start, schedulesBefore[66].start);
assertEq(schedule.end, schedulesBefore[66].end);
assertEq(schedule.lockDuration, 38188800);
assertEq(schedule.cliffDuration, schedulesBefore[66].cliffDuration);
assertEq(schedule.duration, schedulesBefore[66].duration);
assertEq(schedule.periodDuration, schedulesBefore[66].periodDuration);
assertTrue(TLCV1(address(tlcProxy)).isGlobalUnlockedScheduleIgnored(66));
for (uint256 i = 0; i < tlcProxy.getVestingScheduleCount(); i++) {
VestingSchedulesV2.VestingSchedule memory schedule = TLCV1(address(tlcProxy)).getVestingSchedule(i);
assertEq(schedule.lockDuration, newLockDuration[i]);
}
}
}

Expand Down
Loading

0 comments on commit c870119

Please sign in to comment.