Skip to content

Commit

Permalink
feat: Add mainnet forking test case (#4306)
Browse files Browse the repository at this point in the history
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
  • Loading branch information
chrismaree authored and Reinis-FRP committed Dec 28, 2022
1 parent d22ac68 commit 7f551a3
Show file tree
Hide file tree
Showing 25 changed files with 172 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ abstract contract Staker is StakerInterface, Ownable, Lockable, MultiCaller {
// Mapping of delegates to their delegators (staker). Reverse mapping from voterStakes.delegate.
mapping(address => address) public delegateToStaker;

// Number of UMA emitted per second top incentivize stakers.
// Number of UMA emitted per second to incentivize stakers.
uint256 public emissionRate;

// Total number of UMA staked within the system.
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"scripts": {
"test": "yarn hardhat-test && yarn forge-test",
"forge-test": "./scripts/SetUpFoundryWithHardhat.sh && forge test",
"forge-fork-test": "forge test --match-path *fork-test* -vvv --fork-url $CUSTOM_NODE_URL",
"hardhat-test": "hardhat test --network hardhat",
"mocha-test": "mocha ./mocha-test --recursive",
"load-addresses": "yarn hardhat load-addresses",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;

import "../../fixtures/common/CommonTestBase.sol";

import "../../../../contracts/data-verification-mechanism/implementation/VotingV2.sol";
import "../../../../contracts/data-verification-mechanism/interfaces/VotingAncillaryInterface.sol";
import "../../../../contracts/common/interfaces/ExpandedIERC20.sol";

contract CommonDataVerificationMechanismForkTest is CommonTestBase {
VotingV2 voting;
ExpandedIERC20 votingToken;

bool shouldRunForkedTest;

address registeredRequester;
address governor;

bytes32 identifier = bytes32("YES_OR_NO_QUERY");
bytes ancillaryData = bytes("Some data");
uint256 gatMeetingNumOfTokens = 6e24;
uint256 requestTime = 420;

function _commonSetup() public {
uint256 chainId = block.chainid;
shouldRunForkedTest = (chainId == 1 || chainId == 5);
if (!shouldRunForkedTest) return; // Exit early if we are not executing forked tests.

// TODO: look into a way to not have to hard code these addresses. Ok for now as we wont be changing them.
address votingAddress = chainId == 1 ? address(0) : 0xF71cdF8A34c56933A8871354A2570a301364e95F;

voting = VotingV2(votingAddress);

registeredRequester = chainId == 1
? 0xA0Ae6609447e57a42c51B50EAe921D701823FFAe
: 0xA5B9d8a0B0Fa04Ba71BDD68069661ED5C0848884;

governor = chainId == 1
? 0x592349F7DeDB2b75f9d4F194d4b7C16D82E507Dc
: 0xFf0E348389400d7D7510a230361Fc00904429e48;

votingToken = voting.votingToken();
}

function moveToNextPhase() public {
(uint256 phaseLength, ) = voting.voteTiming();
vm.warp(voting.getRoundEndTime(voting.getCurrentRoundId()) - phaseLength);
}

function moveToNextRound() public {
vm.warp(voting.getRoundEndTime(voting.getCurrentRoundId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./CommonDataVerificationMechanismForkTest.sol";

contract FakeLifeCycle is CommonDataVerificationMechanismForkTest {
function setUp() public {
_commonSetup();
}

function test_CanEnqueueRequestAndVoteWithNewlyStakedTokens() public {
if (!shouldRunForkedTest) return; // Exit early if we are not executing forked tests.

// Submit a new request and show it increments.
// Ensure we are at the start of a voting round so we can stake and vote without the stake being disabled.
if (voting.getVotePhase() == VotingV2Interface.Phase.Reveal) moveToNextRound();

uint256 numberRequestsPreRequest = voting.getNumberOfPriceRequests();
vm.prank(registeredRequester);
voting.requestPrice(identifier, requestTime, ancillaryData);
assert(voting.getNumberOfPriceRequests() == numberRequestsPreRequest + 1);

// Mint fresh UMA and stake them.
vm.prank(address(voting));
uint256 stakedNumOfTokens = gatMeetingNumOfTokens;
votingToken.mint(TestAddress.account1, stakedNumOfTokens);
vm.startPrank(TestAddress.account1);
votingToken.approve(address(voting), stakedNumOfTokens);
uint256 stakeTime = voting.getCurrentTime();
voting.stake(stakedNumOfTokens);
assert(voting.getVoterStakePostUpdate(TestAddress.account1) == stakedNumOfTokens);

// Advance some time to ensure reward accrual works as expected.
moveToNextRound();
voting.withdrawRewards(); // Check if the Staker claims rewards now they get the expected amount.
uint256 stakerBalanceAfterRewardWithdrawal = votingToken.balanceOf(TestAddress.account1);
assert(voting.getVoterStakePostUpdate(TestAddress.account1) == stakedNumOfTokens);

uint256 rewardsPerToken =
((voting.getCurrentTime() - stakeTime) * voting.emissionRate() * 1e18) / voting.cumulativeStake();
uint256 expectedRewards = (rewardsPerToken * voting.getVoterStakePostUpdate(TestAddress.account1)) / 1e18;
assertEq(stakerBalanceAfterRewardWithdrawal, expectedRewards);

// Move to next round, request a price and vote on it from the newly staked account.
moveToNextRound();
int256 price = 1e18;
int256 salt = 42069;
uint256 roundId = voting.getCurrentRoundId();
address account = TestAddress.account1;
bytes32 hash =
keccak256(abi.encodePacked(price, salt, account, requestTime, ancillaryData, roundId, identifier));
voting.commitVote(identifier, requestTime, ancillaryData, hash);
moveToNextPhase();
voting.revealVote(identifier, requestTime, price, ancillaryData, salt);

// Check the price has resolved correctly.
moveToNextRound();
vm.stopPrank();
vm.prank(registeredRequester);
assertEq(voting.getPrice(identifier, requestTime, ancillaryData), price);

// Finally, considering we were the only voter, we should be able to work out the slashing amount precisely.
uint256 totalStakedAtVote = voting.cumulativeStake(); // Has not changed from when we staked.
uint256 slashPerTokenPerNoVote =
voting.slashingLibrary().calcNoVoteSlashPerToken(totalStakedAtVote, stakedNumOfTokens, stakedNumOfTokens);
uint256 totalSlashedTokens = ((totalStakedAtVote - stakedNumOfTokens) * slashPerTokenPerNoVote) / 1e18;
uint256 expectedStakerBalanceAfterSlashing = stakedNumOfTokens + totalSlashedTokens;
assertEq(voting.getVoterStakePostUpdate(TestAddress.account1), expectedStakerBalanceAfterSlashing);
}
}
7 changes: 7 additions & 0 deletions packages/core/test/foundry/fixtures/common/CommonTestBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "./TestAddress.sol";

contract CommonTestBase is Test {}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../fixtures/common/CommonTestBase.sol";
import "../fixtures/optimistic-asserter/OptimisticAsserterFixture.sol";
import "../fixtures/common/TestAddress.sol";
import "../../../contracts/data-verification-mechanism/test/MockOracleAncillary.sol";
import "../../../contracts/optimistic-asserter/implementation/test/AssertingCallerTest.sol";

contract Common is Test {
contract CommonOptimisticAsserterTest is CommonTestBase {
// Data structures, that might be used in tests.
struct OracleRequest {
bytes32 identifier;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./Common.sol";
import "./CommonOptimisticAsserterTest.sol";

contract OptimisticAsserterCallbacks is Common {
contract OptimisticAsserterCallbacks is CommonOptimisticAsserterTest {
function setUp() public {
_commonSetup();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./Common.sol";
import "./CommonOptimisticAsserterTest.sol";

contract InvalidParameters is Common {
contract InvalidParameters is CommonOptimisticAsserterTest {
function setUp() public {
_commonSetup();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./Common.sol";
import "./CommonOptimisticAsserterTest.sol";

contract OptimisticAsserterEvents is Common {
contract OptimisticAsserterEvents is CommonOptimisticAsserterTest {
event AdminPropertiesSet(IERC20 defaultCurrency, uint64 defaultLiveness, uint256 burnedBondPercentage);

function setUp() public {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./Common.sol";
import "./CommonOptimisticAsserterTest.sol";

contract SimpleAssertionsWithClaimOnly is Common {
contract SimpleAssertionsWithClaimOnly is CommonOptimisticAsserterTest {
function setUp() public {
_commonSetup();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./Common.sol";
import "./CommonOptimisticAsserterTest.sol";
import "../../../contracts/data-verification-mechanism/implementation/Store.sol";

contract MaintenanceTest is Common {
contract MaintenanceTest is CommonOptimisticAsserterTest {
function setUp() public {
_commonSetup();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./Common.sol";
import "./CommonOptimisticAsserterTest.sol";

contract EscalationManagerPolicyEnforced is Common {
contract EscalationManagerPolicyEnforced is CommonOptimisticAsserterTest {
function setUp() public {
_commonSetup();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/BaseEscalationManager.sol";

contract BaseEscalationManagerTest is Common {
contract BaseEscalationManagerTest is CommonOptimisticAsserterTest {
BaseEscalationManager escalationManager;

bytes32 identifier = "test";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/DisputeLimitingEscalationManager.sol";

contract DisputeLimitingEscalationManagerTest is Common {
contract DisputeLimitingEscalationManagerTest is CommonOptimisticAsserterTest {
DisputeLimitingEscalationManager escalationManager;

bytes32 assertionId = "test";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/FullPolicyEscalationManager.sol";

contract FullPolicyEscalationManagerTest is Common {
contract FullPolicyEscalationManagerTest is CommonOptimisticAsserterTest {
FullPolicyEscalationManager escalationManager;
bytes32 assertionId = bytes32(0);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/OwnerDiscardOracleEscalationManager.sol";

contract OwnerDiscardOracleEscalationManagerTest is Common {
contract OwnerDiscardOracleEscalationManagerTest is CommonOptimisticAsserterTest {
OwnerDiscardOracleEscalationManager escalationManager;

function setUp() public {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/OwnerSelectOracleEscalationManager.sol";

contract OwnerSelectOracleEscalationManagerTest is Common {
contract OwnerSelectOracleEscalationManagerTest is CommonOptimisticAsserterTest {
OwnerSelectOracleEscalationManager escalationManager;

function setUp() public {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/SuperbondEscalationManager.sol";

contract SuperbondEscalationManagerTest is Common {
contract SuperbondEscalationManagerTest is CommonOptimisticAsserterTest {
SuperbondEscalationManager escalationManager;
uint256 superbond = 100e18;
uint256 bond = 50e18;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/WhitelistAsserterEscalationManager.sol";

contract WhitelistAsserterEscalationManagerTest is Common {
contract WhitelistAsserterEscalationManagerTest is CommonOptimisticAsserterTest {
WhitelistAsserterEscalationManager escalationManager;

bytes32 assertionId = "test";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/WhitelistCallerEscalationManager.sol";

contract WhitelistCallerEscalationManagerTest is Common {
contract WhitelistCallerEscalationManagerTest is CommonOptimisticAsserterTest {
WhitelistCallerEscalationManager escalationManager;

function setUp() public {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/escalation-manager/WhitelistDisputerEscalationManager.sol";

contract WhitelistDisputerEscalationManagerTest is Common {
contract WhitelistDisputerEscalationManagerTest is CommonOptimisticAsserterTest {
WhitelistDisputerEscalationManager escalationManager;

function setUp() public {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/examples/DataAsserter.sol";

contract DataAsserterTest is Common {
contract DataAsserterTest is CommonOptimisticAsserterTest {
DataAsserter public dataAsserter;
bytes32 dataId = bytes32("dataId");
bytes32 correctData = bytes32("correctData");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/examples/Insurance.sol";

contract InsuranceTest is Common {
contract InsuranceTest is CommonOptimisticAsserterTest {
Insurance public insurance;
bytes insuredEvent = bytes("insuredEvent");
uint256 insuranceAmount = 100;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../Common.sol";
import "../CommonOptimisticAsserterTest.sol";
import "../../../../contracts/optimistic-asserter/implementation/examples/PredictionMarket.sol";

contract PredictionMarketTestCommon is Common {
contract PredictionMarketTestCommon is CommonOptimisticAsserterTest {
PredictionMarket public predictionMarket;
string outcome1 = "Red";
string outcome2 = "Blue";
Expand Down
Loading

0 comments on commit 7f551a3

Please sign in to comment.