Skip to content

Commit

Permalink
test: Write tests for feeless-votes fix
Browse files Browse the repository at this point in the history
  • Loading branch information
victorges committed Oct 13, 2023
1 parent f52b182 commit 011c5f3
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 4 deletions.
58 changes: 58 additions & 0 deletions src/test/BondingVotesFeeLessVotesFix.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
pragma solidity ^0.8.9;

import "ds-test/test.sol";
import "./base/GovernorBaseTest.sol";
import "contracts/Controller.sol";
import "contracts/bonding/BondingVotes.sol";
import "contracts/bonding/BondingManager.sol";
import "./interfaces/ICheatCodes.sol";

// forge test --match-contract BondingVotesFeeLessVotesFix --fork-url https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY -vvv --fork-block-number 140314540
contract BondingVotesFeeLessVotesFix is GovernorBaseTest {
bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);

BondingManager public constant BONDING_MANAGER = BondingManager(0x35Bcf3c30594191d53231E4FF333E8A770453e40);
IBondingVotes public constant BONDING_VOTES = IBondingVotes(0x0B9C254837E72Ebe9Fe04960C43B69782E68169A);

bytes32 public constant BONDING_VOTES_TARGET_ID = keccak256("BondingVotesTarget");

BondingVotes public newBondingVotesTarget;

address public DELEGATOR = 0xdB18A9353139880d73616e4972a855d66C9B69f0;

function setUp() public {
newBondingVotesTarget = new BondingVotes(address(CONTROLLER));
}

function doUpgrade() internal {
(, gitCommitHash) = CONTROLLER.getContractInfo(BONDING_VOTES_TARGET_ID);

stageAndExecuteOne(
address(CONTROLLER),
0,
abi.encodeWithSelector(
CONTROLLER.setContractInfo.selector,
BONDING_VOTES_TARGET_ID,
address(newBondingVotesTarget),
gitCommitHash
)
);

// Check that new BondingVotesTarget is registered
(address infoAddr, bytes20 infoGitCommitHash) = fetchContractInfo(BONDING_VOTES_TARGET_ID);
assertEq(infoAddr, address(newBondingVotesTarget));
assertEq(infoGitCommitHash, gitCommitHash);
}

function testBeforeUpgrade() public {
CHEATS.expectRevert(arithmeticError);
BONDING_VOTES.getVotes(DELEGATOR);
}

function testAfterUpgrade() public {
doUpgrade();

uint256 votes = BONDING_VOTES.getVotes(DELEGATOR);
assertTrue(votes > 0);
}
}
137 changes: 136 additions & 1 deletion test/integration/BondingVotes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import RPC from "../../utils/rpc"
import setupIntegrationTest from "../helpers/setupIntegrationTest"
import {createWinningTicket, getTicketHash} from "../helpers/ticket"
import signMsg from "../helpers/signMsg"

import chai, {assert} from "chai"
import {ethers} from "hardhat"
Expand All @@ -18,10 +20,12 @@ describe("BondingVotes", () => {
let bondingVotes
let bondingManager
let roundsManager
let roundLength
let ticketBroker
let token
let minter

let roundLength

const PERC_DIVISOR = 1000000
const PERC_MULTIPLIER = PERC_DIVISOR / 100

Expand Down Expand Up @@ -59,6 +63,11 @@ describe("BondingVotes", () => {
)
roundLength = (await roundsManager.roundLength()).toNumber()

ticketBroker = await ethers.getContractAt(
"TicketBroker",
fixture.TicketBroker.address
)

const controller = await ethers.getContractAt(
"Controller",
fixture.Controller.address
Expand Down Expand Up @@ -87,6 +96,9 @@ describe("BondingVotes", () => {

const nextRound = async (rounds = 1) => {
await roundsManager.mineBlocks(rounds * roundLength)
await roundsManager.setBlockHash(
ethers.utils.solidityKeccak256(["string"], ["bar"])
)
await roundsManager.initializeRound()
const currRound = (await roundsManager.currentRound()).toNumber()
mintableTokens[currRound] = await minter.currentMintableTokens()
Expand Down Expand Up @@ -922,5 +934,128 @@ describe("BondingVotes", () => {
}
})
})

describe("transcoder with uninitialized fee factor", () => {
let broadcaster

before(async () => {
broadcaster = signers[2]

// Round R

// broadcaster sets up deposit/reserve
const deposit = ethers.utils.parseEther("1")
await ticketBroker
.connect(broadcaster)
.fundDeposit({value: deposit})

const reserve = ethers.utils.parseEther("1")
await ticketBroker
.connect(broadcaster)
.fundReserve({value: reserve})

// Round R+1
await nextRound()

// Now redeem a ticket for the transcoder
const creationRound = await roundsManager.currentRound()
const creationRoundBlockHash =
await roundsManager.blockHashForRound(creationRound)
console.log(creationRoundBlockHash)
const auxData = ethers.utils.solidityPack(
["uint256", "bytes32"],
[creationRound, creationRoundBlockHash]
)
const recipientRand = 5
const faceValue = 1000
const ticket = createWinningTicket(
transcoder.address,
broadcaster.address,
recipientRand,
faceValue,
auxData
)
const senderSig = await signMsg(
getTicketHash(ticket),
broadcaster.address
)

await ticketBroker
.connect(transcoder)
.redeemWinningTicket(ticket, senderSig, recipientRand)

// delegator bonds to transcoder
await bond(delegator, lptAmount(1), transcoder)
})

it("should be in round currentRound+1", async () => {
const curr = await roundsManager.currentRound()
expect(curr).to.equal(currentRound + 1)
})

it("should have a non-zero cumulativeFeeFactor for transcoder", async () => {
const earningsPool =
await bondingManager.getTranscoderEarningsPoolForRound(
transcoder.address,
currentRound + 1
)
expect(earningsPool.cumulativeFeeFactor).to.not.equal(0)
})

it("should be able to calculate votes on the current round", async () => {
await expectStakeAt(
delegator,
currentRound + 1,
0,
constants.AddressZero
)
await expectStakeAt(
delegator,
currentRound + 2,
lptAmount(1),
transcoder.address
)
})

describe("in a round with cumulativeFeeFactor not initialized", async () => {
before(async () => {
// R+2
await nextRound()

await bondingManager.connect(transcoder).reward()
})

it("should not have initialized cumulativeFeeFactor", async () => {
const earningsPool =
await bondingManager.getTranscoderEarningsPoolForRound(
transcoder.address,
currentRound + 2
)
expect(earningsPool.cumulativeFeeFactor).to.equal(0)
expect(earningsPool.cumulativeRewardFactor).not.to.equal(0)
})

it("should be able to calculate votes on next round", async () => {
await expectStakeAt(
delegator,
currentRound + 1,
0,
constants.AddressZero
)
await expectStakeAt(
delegator,
currentRound + 2,
lptAmount(1),
transcoder.address
)
await expectStakeAt(
delegator,
currentRound + 3,
"1234396725000000000", // 1 LPT + rewards
transcoder.address
)
})
})
})
})
})
44 changes: 41 additions & 3 deletions test/unit/BondingVotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -962,16 +962,17 @@ describe("BondingVotes", () => {
const setEarningPoolRewardFactor = async (
address,
round,
factor
rewardFactor,
feeFactor = 0
) => {
await fixture.bondingManager.setMockTranscoderEarningsPoolForRound(
address,
round,
0,
0,
0,
factor,
0
rewardFactor,
feeFactor
)
}

Expand Down Expand Up @@ -1152,6 +1153,43 @@ describe("BondingVotes", () => {
)
})

it("should not fail if there's no cumulativeFeeFactor on the lastRewardRound", async () => {
await checkpointDelegator({
startRound: currentRound - 9,
bondedAmount: 1000,
delegateAddress: transcoder.address,
lastClaimRound: currentRound - 10
})
await setEarningPoolRewardFactor(
transcoder.address,
currentRound - 10,
PERC_DIVISOR,
PERC_DIVISOR.mul(11).div(10) // 1.1 fee factor
)

await checkpointTranscoder({
account: transcoder.address,
startRound: currentRound - 1,
lastRewardRound: currentRound - 2
})
await setEarningPoolRewardFactor(
transcoder.address,
currentRound - 2,
PERC_DIVISOR,
0 // uninitialized fee factor
)

assert.deepEqual(
await bondingVotes
.getVotesAndDelegateAtRoundStart(
delegator.address,
currentRound
)
.then(t => t.map(v => v.toString())),
["1000", transcoder.address]
)
})

it("should return the bonded amount with accrued pending rewards since lastClaimRound", async () => {
await checkpointDelegator({
startRound: currentRound - 9,
Expand Down

0 comments on commit 011c5f3

Please sign in to comment.