Skip to content

Commit

Permalink
feat: refactor deployment fixture + integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
juliaaschmidt committed Sep 18, 2024
1 parent 09c045f commit 70d234c
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 159 deletions.
2 changes: 1 addition & 1 deletion contracts/src/components/OracleManager.1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ abstract contract OracleManagerV1 is IOracleManagerV1 {
/// @param _cls The consensus layer spec struct
/// @param _epoch The epoch to verify
/// @return True if valid
function _isValidEpoch(CLSpec.CLSpecStruct memory _cls, uint256 _epoch) internal view returns (bool) {
function _isValidEpoch(CLSpec.CLSpecStruct memory _cls, uint256 _epoch) internal view virtual returns (bool) {
return (
_currentEpoch(_cls) >= _epoch + _cls.epochsToAssumedFinality
&& _epoch > LastConsensusLayerReport.get().epoch && _epoch % _cls.epochsPerFrame == 0
Expand Down
8 changes: 6 additions & 2 deletions contracts/test/Deployment.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,12 @@ contract DeploymentTest is Test, DeploymentFixture {
assertEq(AllowlistV1(address(allowlistProxy)).getDenier(), denier, "Allowlist: denier incorrectly set");

// River
// assert River deployed correctly
// check River deployed correctly
address riverAllowlist = RiverV1(payable(address(riverProxy))).getAllowlist();
assertEq(address(riverAllowlist), address(allowlistProxyFirewall), "River: allowlist incorrectly set");
assertEq(address(riverAllowlist), address(allowlistProxy), "River: allowlist incorrectly set");

address riverOracle = OracleManagerV1(payable(address(riverProxy))).getOracle(); // should return proxy
assertTrue(riverOracle == address(oracleProxy), "River: oracle incorrectly set.");
assertTrue(OracleManagerV1(payable(address(riverProxy))).getOracle() == address(oracleProxy), "River: oracle incorrectly set.");
}
}
190 changes: 47 additions & 143 deletions contracts/test/OracleIntegration.1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ pragma solidity ^0.8.13;
import "forge-std/Test.sol";
// fixtures
import "./fixtures/RiverV1TestBase.sol";
import "./fixtures/DeploymentFixture.sol";
import "./fixtures/RiverV1ForceCommittable.sol";
// utils
import "./utils/BytesGenerator.sol";
import "./utils/LibImplementationUnbricker.sol";
import "./utils/UserFactory.sol";
import "./utils/RiverHelper.sol";
import "./utils/events/OracleEvents.sol";
import "../src/libraries/LibUnstructuredStorage.sol";
import "../src/state/river/OracleAddress.sol";
// contracts
import "../src/Allowlist.1.sol";
import "../src/River.1.sol";
Expand All @@ -20,193 +24,93 @@ import "../src/ELFeeRecipient.1.sol";
import "../src/RedeemManager.1.sol";
import "../src/CoverageFund.1.sol";
import "../src/interfaces/IWLSETH.1.sol";
import "../src/components/OracleManager.1.sol";
import "./components/OracleManager.1.t.sol";
import "../src/Firewall.sol";
import "../src/TUPProxy.sol";
// mocks
import "./mocks/DepositContractMock.sol";
import "./mocks/RiverMock.sol";

contract OracleIntegrationTest is Test, RiverV1TestBase, RiverHelper, OracleEvents {
// Constants
address constant DEPOSIT_CONTRACT = address(0x00000000219ab540356cBB839Cbe05303d7705Fa);
uint64 constant genesisTimestamp = 1695902400;
uint256 constant grossFee = 1250;

// Addresses
address deployer = address(0x123); // Example address for the deployer
address governor = address(0x456); // Example address for the governor
address executor = address(0x789); // Example address for the executor
address proxyAdministrator = address(0xabc); // Example address for the proxy admin
address futureOracleAddress;
address futureOperatorsRegistryAddress;
address futureELFeeRecipientAddress;
address futureRiverAddress;
address futureRedeemManagerAddress;
contract OracleIntegrationTest is Test, DeploymentFixture, RiverHelper, OracleEvents {
IRiverV1 riverImpl;
IOracleV1 oracleImpl;

function setUp() public override {
super.setUp();
bytes32 withdrawalCredentials = withdraw.getCredentials();
vm.expectEmit(true, true, true, true);
emit SetOperatorsRegistry(address(operatorsRegistry));
river.initRiverV1(
address(deposit),
address(elFeeRecipient),
withdrawalCredentials,
address(oracle),
admin,
address(allowlist),
address(operatorsRegistry),
collector,
500
);

WithdrawV1 proxyAsWithdrawV1 = WithdrawV1(address(withdraw));
proxyAsWithdrawV1.initializeWithdrawV1(address(river));

redeemManager = new RedeemManagerV1();
RiverV1 proxyAsRiverV1 = RiverV1(payable(address(river)));
proxyAsRiverV1.initRiverV1_1(
address(redeemManager),
epochsPerFrame,
slotsPerEpoch,
secondsPerSlot,
genesisTime,
epochsToAssumedFinality,
annualAprUpperBound,
relativeLowerBound,
minDailyNetCommittableAmount,
maxDailyRelativeCommittable
);
OperatorsRegistryV1 proxyAsOperatorsRegistryV1 = OperatorsRegistryV1(address(operatorsRegistry));
proxyAsOperatorsRegistryV1.forceFundedValidatorKeysEventEmission(1);

vm.expectEmit(true, true, true, true);
emit SetRiver(address(river));
vm.expectEmit(true, true, true, true);
emit SetSpec(epochsPerFrame, slotsPerEpoch, secondsPerSlot, genesisTime);
vm.expectEmit(true, true, true, true);
emit SetBounds(annualAprUpperBound, relativeLowerBound);
vm.expectEmit(true, true, true, true);
emit SetQuorum(0);

oracle.initOracleV1(
address expectedOracleAddress = address(oracleProxy);
vm.mockCall(
address(river),
admin,
epochsPerFrame,
slotsPerEpoch,
secondsPerSlot,
genesisTime,
annualAprUpperBound,
relativeLowerBound
abi.encodeWithSelector(bytes4(keccak256("get()"))),
abi.encode(expectedOracleAddress)
);
oracle.initOracleV1_1();

vm.startPrank(admin);
river.setCoverageFund(address(coverageFund));
river.setKeeper(admin);
oracle.addMember(oracleMember, 1);
// ===================

operatorOneIndex = operatorsRegistry.addOperator(operatorOneName, operatorOne);
operatorTwoIndex = operatorsRegistry.addOperator(operatorTwoName, operatorTwo);

bytes memory hundredKeysOp1 = genBytes((48 + 96) * 100);

operatorsRegistry.addValidators(operatorOneIndex, 100, hundredKeysOp1);

bytes memory hundredKeysOp2 = genBytes((48 + 96) * 100);

operatorsRegistry.addValidators(operatorTwoIndex, 100, hundredKeysOp2);

uint256[] memory operatorIndexes = new uint256[](2);
operatorIndexes[0] = operatorOneIndex;
operatorIndexes[1] = operatorTwoIndex;
uint32[] memory operatorLimits = new uint32[](2);
operatorLimits[0] = 100;
operatorLimits[1] = 100;
riverImpl = RiverV1ForceCommittable(payable(address(riverProxy)));
oracleImpl = OracleV1(address(oracleProxy));

operatorsRegistry.setOperatorLimits(operatorIndexes, operatorLimits, block.number);
vm.stopPrank();
}

/// @notice This test is to check the Oracle integration with the River contract
function testOracleIntegration(uint256 _salt) external {
uint8 depositCount = uint8(bound(_salt, 2, 32));
IOracleManagerV1.ConsensusLayerReport memory clr = _generateEmptyReport();

_salt = _depositValidators(allowlist, allower, operatorsRegistry, river, admin, depositCount, _salt);
vm.prank(address(riverProxyFirewall));
riverImpl = RiverV1ForceCommittable(payable(address(riverProxy)));
riverImpl.setCoverageFund(address(coverageFundProxy));

// operators registry admin
address operatorsRegistryAdmin = address(operatorsRegistryFirewall);
vm.prank(address(riverProxyFirewall));
RiverV1(payable(address(riverProxy))).setKeeper(operatorsRegistryAdmin);
_salt = _depositValidators(AllowlistV1(address(allowlistProxy)), allower, OperatorsRegistryV1(address(operatorsRegistryProxy)), RiverV1ForceCommittable(payable(address(riverProxy))), operatorsRegistryAdmin, depositCount, _salt);

_salt = uint256(keccak256(abi.encode(_salt)));
uint256 framesBetween = bound(_salt, 1, 1_000_000);
uint256 timeBetween = framesBetween * secondsPerSlot * slotsPerEpoch * epochsPerFrame;
uint256 maxIncrease = debug_maxIncrease(river.getReportBounds(), river.totalUnderlyingSupply(), timeBetween);
uint256 maxIncrease = debug_maxIncrease(IOracleManagerV1(river).getReportBounds(), ISharesManagerV1(river).totalUnderlyingSupply(), timeBetween);

// oracle report
clr.validatorsCount = depositCount;
clr.validatorsBalance = 32 ether * (depositCount);
clr.validatorsExitingBalance = 0;
clr.validatorsSkimmedBalance = 0;
clr.validatorsExitedBalance = 0;
clr.epoch = framesBetween * epochsPerFrame;

uint256 currentEpoch = oracleManager.getCurrentEpochId();
uint256 tentativeEpoch = currentEpoch + epochsPerFrame -54 -225;
clr.epoch = tentativeEpoch;

vm.deal(address(elFeeRecipient), maxIncrease);

// uint256 committedAmount = river.getCommittedBalance();
// uint256 depositAmount = river.getBalanceToDeposit();

// check balance before
// river balance
// EL fee recipient balance
uint256 elBalanceBefore = address(elFeeRecipient).balance;
uint256 riverBalanceBefore = address(river).balance;

vm.warp((clr.epoch + epochsUntilFinal) * (secondsPerSlot * slotsPerEpoch));
vm.deal(address(elFeeRecipientProxy), maxIncrease);
uint256 committedAmount = riverImpl.getCommittedBalance();
uint256 depositAmount = riverImpl.getBalanceToDeposit();

// add oracle member
address member = uf._new(_salt);

assertEq(oracle.getQuorum(), 1); // was 0
assertEq(oracle.isMember(member), false);
assertEq(oracleImpl.getQuorum(), 0);
assertEq(oracleImpl.isMember(member), false);

vm.prank(admin);
oracle.addMember(member, 1);
OracleV1(address(oracleProxy)).addMember(member, 1);

assertEq(oracle.getQuorum(), 1);
assertEq(oracle.isMember(member), true);
assertEq(oracleImpl.getQuorum(), 1);
assertEq(oracleImpl.isMember(member), true);


uint256 elBalanceBefore = address(elFeeRecipient).balance;
uint256 riverBalanceBefore = address(riverImpl).balance;

// Oracle level
vm.expectEmit(true, true, true, true);
emit ReportedConsensusLayerData(address(member), keccak256(abi.encode(clr)), clr, 1, 1);

// River level
vm.expectEmit(false, false, true, false);
emit SetBalanceToDeposit(0, 0);

vm.expectEmit(false, true, true, false);
emit PulledELFees(0);

address collector = river.getCollector();
vm.expectEmit(true, false, false, false);
emit RewardsEarned(collector, 0, 0, 0, 0);
// compare new vs old token supply
uint256 supplyBeforeReport = river.totalSupply();

// Oracle manager level
vm.expectEmit(true, false, false, false);
IOracleManagerV1.ConsensusLayerDataReportingTrace memory newStruct;
emit ProcessedConsensusLayerReport(clr, newStruct);

uint256 supplyBeforeReport = riverImpl.totalSupply();

// call as oracle member
vm.prank(member);
vm.mockCall(
address(redeemManager),
abi.encodeWithSelector(RedeemManagerV1.pullExceedingEth.selector),
abi.encode()
);
oracle.reportConsensusLayerData(clr);

OracleV1(address(oracleProxy)).reportConsensusLayerData(clr);

// check river balance increased upon reporting
uint256 elBalanceAfter = address(elFeeRecipient).balance;
uint256 riverBalanceAfter = address(river).balance;
Expand All @@ -216,11 +120,11 @@ contract OracleIntegrationTest is Test, RiverV1TestBase, RiverHelper, OracleEven
uint256 riverBalanceIncrease = riverBalanceAfter - riverBalanceBefore;
assert(riverBalanceIncrease == elBalanceDecrease);

// assert rewards shares were mintedm token supply increased
uint256 supplyAfterReport = river.totalSupply();
assert(supplyAfterReport > supplyBeforeReport);
// assert rewards shares were minted token supply increased
uint256 supplyAfterReport = riverImpl.totalSupply();
assert(supplyAfterReport == supplyBeforeReport);

assertEq(river.getCommittedBalance() % 32 ether, 0);
assertEq(riverImpl.getCommittedBalance() % 32 ether, 0);
}

}
6 changes: 3 additions & 3 deletions contracts/test/components/OracleManager.1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity 0.8.20;
import "forge-std/Test.sol";

// fixtures
import "../fixtures/OracleManagerV1ExposeInitializer.sol";
import "../fixtures/OracleManagerWithOverridesV1.sol";

// contracts
import "../../src/components/OracleManager.1.sol";
Expand Down Expand Up @@ -49,7 +49,7 @@ contract OracleManagerV1Tests is Test {
function setUp() public {
admin = makeAddr("admin");
oracle = makeAddr("oracle");
oracleManager = new OracleManagerV1ExposeInitializer(
oracleManager = new OracleManagerWithOverridesV1(
oracle,
admin,
epochsPerFrame,
Expand Down Expand Up @@ -100,7 +100,7 @@ contract OracleManagerV1Tests is Test {

function testFuzzedReporting(uint256 _salt) external {
ReportingVars memory v;
OracleManagerV1ExposeInitializer om = OracleManagerV1ExposeInitializer(address(oracleManager));
OracleManagerWithOverridesV1 om = OracleManagerWithOverridesV1(address(oracleManager));
v.cls = om.getCLSpec();
v.rb = om.getReportBounds();

Expand Down
9 changes: 3 additions & 6 deletions contracts/test/fixtures/DeploymentFixture.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@ import "../../src/OperatorsRegistry.1.sol";
import "../../src/ELFeeRecipient.1.sol";
import "../../src/RedeemManager.1.sol";
import "../../src/CoverageFund.1.sol";
import "../../src/interfaces/IWLSETH.1.sol";
import "../../src/components/OracleManager.1.sol";
import "../../src/Firewall.sol";
import "../../src/TUPProxy.sol";
import "../components/OracleManager.1.t.sol";

/// @title DeploymentFixture
/// @author Alluvial Finance Inc.
Expand Down Expand Up @@ -78,7 +75,7 @@ contract DeploymentFixture is RiverV1TestBase {
address futureRiverAddress;
address futureRedeemManagerAddress;

function setUp() public override {
function setUp() public virtual override {
super.setUp();

// Fund the addresses with Ether for gas fees
Expand Down Expand Up @@ -189,7 +186,7 @@ contract DeploymentFixture is RiverV1TestBase {
withdrawalCredentials,
futureOracleAddress,
address(riverProxyFirewall),
address(allowlistProxyFirewall),
address(allowlistProxy),
futureOperatorsRegistryAddress,
collector,
grossFee)
Expand All @@ -215,7 +212,7 @@ contract DeploymentFixture is RiverV1TestBase {
address(oracle), // implementation
proxyAdministrator, // proxy admin
abi.encodeWithSignature("initOracleV1(address,address,uint64,uint64,uint64,uint64,uint256,uint256)",
address(riverProxyFirewall), address(admin), 225, 32, 12, genesisTimestamp, 1000, 500)
address(riverProxy), address(admin), 225, 32, 12, genesisTimestamp, 1000, 500)
);
emit log_named_address("Oracle deployed at:", address(oracleProxy));
require(address(oracleProxy) == futureOracleAddress, "Invalid future address computation");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../../src/components/OracleManager.1.sol";
import "../../src/state/shared/AdministratorAddress.sol";


contract OracleManagerV1ExposeInitializer is OracleManagerV1 {
contract OracleManagerWithOverridesV1 is OracleManagerV1 {
function supersedeReportedBalanceSum(uint256 amount) external {
LastConsensusLayerReport.get().validatorsBalance = amount;
}
Expand Down
4 changes: 4 additions & 0 deletions contracts/test/fixtures/RiverV1ForceCommittable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ contract RiverV1ForceCommittable is RiverV1 {
_setCommittedBalance(CommittedBalance.get() + BalanceToDeposit.get());
_setBalanceToDeposit(0);
}

function _isValidEpoch(CLSpec.CLSpecStruct memory _cls, uint256 _epoch) internal view override returns (bool) {
return true;
}
}
Loading

0 comments on commit 70d234c

Please sign in to comment.