Skip to content

Commit

Permalink
test: adding tests after implementing fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kupermind committed Jul 8, 2024
1 parent 1f56a08 commit acf3e38
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 26 deletions.
2 changes: 1 addition & 1 deletion contracts/Dispenser.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,7 @@ contract Dispenser {
_locked = 1;
}

/// @dev Syncs the withheld amount according to the data received from L2.
/// @dev Syncs the withheld token amount according to the data received from L2.
/// @notice Only a corresponding chain Id deposit processor is able to communicate the withheld amount data.
/// Note that by design only a normalized withheld amount is delivered from L2.
/// @param chainId L2 chain Id the withheld amount data is communicated from.
Expand Down
2 changes: 1 addition & 1 deletion contracts/staking/DefaultTargetDispenserL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ abstract contract DefaultTargetDispenserL2 is IBridgeErrors {

/// @dev Syncs withheld token amount with L1.
/// @param bridgePayload Payload data for the bridge relayer.
function syncWithheldTokens(bytes memory bridgePayload) external payable {
function syncWithheldAmount(bytes memory bridgePayload) external payable {
// Reentrancy guard
if (_locked > 1) {
revert ReentrancyGuard();
Expand Down
Binary file modified docs/StakingSmartContracts.pdf
Binary file not shown.
138 changes: 133 additions & 5 deletions test/DispenserStakingIncentives.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,6 @@ describe("DispenserStakingIncentives", async () => {

// Set staking fraction to 100%
await tokenomics.changeIncentiveFractions(0, 0, 0, 0, 0, 100);
// Changing staking parameters
await tokenomics.changeStakingParams(50, 10);

// Checkpoint to apply changes
await helpers.time.increase(epochLen);
Expand Down Expand Up @@ -728,6 +726,44 @@ describe("DispenserStakingIncentives", async () => {
await snapshot.restore();
});

it("Should fail when trying to claim staking incentives for a retainer", async () => {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();

// Set staking fraction to 100%
await tokenomics.changeIncentiveFractions(0, 0, 0, 0, 0, 100);

// Checkpoint to apply changes
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

// Unpause the dispenser
await dispenser.setPauseState(0);

// Add deployer as a retainer nominee
await vw.addNominee(convertBytes32ToAddress(retainer), chainId);

// Vote for the retainer
await vw.setNomineeRelativeWeight(convertBytes32ToAddress(retainer), chainId, defaultWeight);

// Checkpoint to get to the next epoch
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

// Try to claim incentives for the retainer
await expect(
dispenser.claimStakingIncentives(numClaimedEpochs, chainId, retainer, bridgePayload)
).to.be.revertedWithCustomError(dispenser, "WrongAccount");

// Try to claim incentives for the retainer in the batch
await expect(
dispenser.claimStakingIncentivesBatch(numClaimedEpochs, [chainId], [[retainer]], [bridgePayload], [0])
).to.be.revertedWithCustomError(dispenser, "WrongAccount");

// Restore to the state of the snapshot
await snapshot.restore();
});

it("Sync withheld amount maintenance (DAO)", async () => {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();
Expand Down Expand Up @@ -814,7 +850,15 @@ describe("DispenserStakingIncentives", async () => {

// Claiming is not possible as it's the epoch after the staking contract was removed from nominees
await expect(
dispenser.claimStakingIncentives(numClaimedEpochs, chainId, stakingTarget, bridgePayload)
dispenser.claimStakingIncentives(numClaimedEpochs + 1, chainId, stakingTarget, bridgePayload)
).to.be.revertedWithCustomError(dispenser, "Overflow");

// Wait for one more epoch and try again
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

await expect(
dispenser.claimStakingIncentives(numClaimedEpochs + 1, chainId, stakingTarget, bridgePayload)
).to.be.revertedWithCustomError(dispenser, "Overflow");

// Restore to the state of the snapshot
Expand Down Expand Up @@ -865,7 +909,7 @@ describe("DispenserStakingIncentives", async () => {
).to.be.revertedWithCustomError(dispenser, "DepositProcessorOnly");

// Sync back the withheld amount
await gnosisTargetDispenserL2.syncWithheldTokens(gnosisBridgePayload);
await gnosisTargetDispenserL2.syncWithheldAmount(gnosisBridgePayload);

// Add a valid staking target nominee
await vw.addNominee(stakingInstance.address, gnosisChainId);
Expand Down Expand Up @@ -899,6 +943,90 @@ describe("DispenserStakingIncentives", async () => {
await snapshot.restore();
});

it("Should not claim anything is staking fraction is zero", async () => {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();

// Set all fractions to zero
await tokenomics.changeIncentiveFractions(0, 0, 0, 0, 0, 0);

// Checkpoint to apply changes
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

// Unpause the dispenser
await dispenser.setPauseState(0);

// Add a non-whitelisted staking instance as a nominee
await vw.addNominee(stakingInstance.address, chainId);

const stakingTarget = convertAddressToBytes32(stakingInstance.address);

// Vote for the nominee
await vw.setNomineeRelativeWeight(stakingInstance.address, chainId, defaultWeight);

// Checkpoint to account for weights
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

// Get the staking inflation for the previous epoch
const lastPoint = await tokenomics.epochCounter() - 1;
// Get the staking point of the last epoch
let sp = await tokenomics.mapEpochStakingPoints(lastPoint);
const sIncentive = sp.stakingIncentive;

// Claim with withheld amount being accounted for
await dispenser.claimStakingIncentives(numClaimedEpochs, chainId, stakingTarget, bridgePayload);

// Check that no OLAS has been distributed
expect(await olas.balanceOf(stakingInstance.address)).to.equal(0);

// All the staking incentives must be returned into current epoch
sp = await tokenomics.mapEpochStakingPoints(lastPoint + 1);
expect(sp.stakingIncentive).to.equal(sIncentive);

// Restore to the state of the snapshot
await snapshot.restore();
});

it("Return all the staking inflation if there is no nominee", async () => {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();

// Set staking fraction to 100%
await tokenomics.changeIncentiveFractions(0, 0, 0, 0, 0, 100);
// Changing staking parameters
await tokenomics.changeStakingParams(100, 10);

// Checkpoint to apply changes
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

// Unpause the dispenser
await dispenser.setPauseState(0);

// Add a non-whitelisted staking instance as a nominee
await vw.addNominee(stakingInstance.address, chainId);

const stakingTarget = convertAddressToBytes32(stakingInstance.address);

// Vote for the nominee
await vw.setNomineeRelativeWeight(stakingInstance.address, chainId, 0);

// Checkpoint to account for weights
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();

// Claim with withheld amount being accounted for
await dispenser.claimStakingIncentives(numClaimedEpochs, chainId, stakingTarget, bridgePayload);

// Check that no OLAS has been distributed
expect(await olas.balanceOf(stakingInstance.address)).to.equal(0);

// Restore to the state of the snapshot
await snapshot.restore();
});

it("Claim staking incentives for a single nominee with bridging decimals lower than 18", async () => {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();
Expand Down Expand Up @@ -986,7 +1114,7 @@ describe("DispenserStakingIncentives", async () => {
expect(await gnosisTargetDispenserL2.withheldAmount()).to.gt(0);

// Sync back the withheld amount
await gnosisTargetDispenserL2.syncWithheldTokens(gnosisBridgePayload);
await gnosisTargetDispenserL2.syncWithheldAmount(gnosisBridgePayload);

// Get another staking instance
const MockStakingProxy = await ethers.getContractFactory("MockStakingProxy");
Expand Down
38 changes: 19 additions & 19 deletions test/StakingBridging.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,11 +402,11 @@ describe("StakingBridging", async () => {
expect(Number(withheldAmount)).to.equal(stakingIncentive);

// Send withheld amount from L2 to L1
await arbitrumTargetDispenserL2.syncWithheldTokens("0x");
await arbitrumTargetDispenserL2.syncWithheldAmount("0x");

// Try to send withheld amount from L2 to L1 when there is none
await expect(
arbitrumTargetDispenserL2.syncWithheldTokens("0x")
arbitrumTargetDispenserL2.syncWithheldAmount("0x")
).to.be.revertedWithCustomError(arbitrumDepositProcessorL1, "ZeroValue");

// Get staking batch hash
Expand Down Expand Up @@ -653,30 +653,30 @@ describe("StakingBridging", async () => {

// Trying to sync withheld tokens when paused
await expect(
gnosisTargetDispenserL2.syncWithheldTokens("0x")
gnosisTargetDispenserL2.syncWithheldAmount("0x")
).to.be.revertedWithCustomError(gnosisTargetDispenserL2, "Paused");

// Unpause and send withheld amount from L2 to L1
await gnosisTargetDispenserL2.unpause();

// Send withheld token info from L2 to L1 when the gas is going to be adjusted from zero
let bridgePayload = ethers.utils.defaultAbiCoder.encode(["uint256"], [0]);
await gnosisTargetDispenserL2.syncWithheldTokens(bridgePayload);
await gnosisTargetDispenserL2.syncWithheldAmount(bridgePayload);

// Send a message on L2 with funds for a wrong address
await dispenser.mintAndSend(gnosisDepositProcessorL1.address, deployer.address, stakingIncentive, "0x",
stakingIncentive);

// Send withheld token info from L2 to L1 when the gas is going to be adjusted without any payload
await gnosisTargetDispenserL2.syncWithheldTokens("0x");
await gnosisTargetDispenserL2.syncWithheldAmount("0x");

// Send a message on L2 with funds for a wrong address
await dispenser.mintAndSend(gnosisDepositProcessorL1.address, deployer.address, stakingIncentive, "0x",
stakingIncentive);

// Send withheld token info from L2 to L1 when the gas is going to be adjusted from being too high
bridgePayload = ethers.utils.defaultAbiCoder.encode(["uint256"], [moreThanMaxUint96]);
await gnosisTargetDispenserL2.syncWithheldTokens(bridgePayload);
await gnosisTargetDispenserL2.syncWithheldAmount(bridgePayload);
});

it("Verify senders on L1 and L2", async function () {
Expand Down Expand Up @@ -704,7 +704,7 @@ describe("StakingBridging", async () => {

// Try to receive a message with the wrong sender
await expect(
gnosisTargetDispenserL2.syncWithheldTokens(HashZero)
gnosisTargetDispenserL2.syncWithheldAmount(HashZero)
).to.be.revertedWithCustomError(gnosisDepositProcessorL1, "WrongMessageSender");

// Deploy another bridge relayer
Expand Down Expand Up @@ -781,22 +781,22 @@ describe("StakingBridging", async () => {

// Send withheld amount from L2 to L1 with the zero gas limit set
bridgePayload = ethers.utils.defaultAbiCoder.encode(["uint256"], [0]);
await optimismTargetDispenserL2.syncWithheldTokens(bridgePayload);
await optimismTargetDispenserL2.syncWithheldAmount(bridgePayload);

// Send a message on L2 with funds for a wrong address
await dispenser.mintAndSend(optimismDepositProcessorL1.address, deployer.address, stakingIncentive, bridgePayload,
stakingIncentive);

// Send withheld amount from L2 to L1 with the more than recommended gas limit
bridgePayload = ethers.utils.defaultAbiCoder.encode(["uint256"], [moreThanMaxUint96]);
await optimismTargetDispenserL2.syncWithheldTokens(bridgePayload);
await optimismTargetDispenserL2.syncWithheldAmount(bridgePayload);

// Send a message on L2 with funds for a wrong address
await dispenser.mintAndSend(optimismDepositProcessorL1.address, deployer.address, stakingIncentive, bridgePayload,
stakingIncentive);

// Send withheld amount from L2 to L1 without any bridge payload
await optimismTargetDispenserL2.syncWithheldTokens("0x");
await optimismTargetDispenserL2.syncWithheldAmount("0x");
});
});

Expand Down Expand Up @@ -849,7 +849,7 @@ describe("StakingBridging", async () => {
expect(Number(withheldAmount)).to.equal(stakingIncentive);

// Send withheld amount from L2 to L1
await polygonTargetDispenserL2.syncWithheldTokens("0x");
await polygonTargetDispenserL2.syncWithheldAmount("0x");
});
});

Expand Down Expand Up @@ -951,7 +951,7 @@ describe("StakingBridging", async () => {
// Try to send withheld amount from L2 to L1 with insufficient normalized withheld amount
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [deployer.address, 0]);
await expect(
wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload, {value: defaultMsgValue})
wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload, {value: defaultMsgValue})
).to.be.revertedWithCustomError(wormholeTargetDispenserL2, "ZeroValue");

// Send a message on L2 with funds for a wrong address with a bigger amount
Expand All @@ -961,12 +961,12 @@ describe("StakingBridging", async () => {
// Try to send withheld amount from L2 to L1 with a zero refund address
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [AddressZero, 0]);
await expect(
wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload, {value: defaultMsgValue})
wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload, {value: defaultMsgValue})
).to.be.revertedWithCustomError(wormholeTargetDispenserL2, "ZeroAddress");

// Send withheld amount from L2 to L1
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [deployer.address, 0]);
await wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload, {value: defaultMsgValue});
await wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload, {value: defaultMsgValue});
});

it("Checks during a message sending on L1 and L2", async function () {
Expand Down Expand Up @@ -995,13 +995,13 @@ describe("StakingBridging", async () => {

// Try to send withheld tokens with an incorrect payload
await expect(
wormholeTargetDispenserL2.syncWithheldTokens("0x")
wormholeTargetDispenserL2.syncWithheldAmount("0x")
).to.be.revertedWithCustomError(wormholeTargetDispenserL2, "IncorrectDataLength");

// Try to send withheld tokens without any msg.value covering the cost
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [deployer.address, 0]);
await expect(
wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload)
wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload)
).to.be.revertedWithCustomError(wormholeTargetDispenserL2, "LowerThan");
});

Expand Down Expand Up @@ -1062,13 +1062,13 @@ describe("StakingBridging", async () => {
await bridgeRelayer.setMode(3);
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [deployer.address, 0]);
await expect(
wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload, {value: defaultMsgValue})
wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload, {value: defaultMsgValue})
).to.be.revertedWithCustomError(wormholeTargetDispenserL2, "WrongChainId");

// Try to send withheld amount from L2 to L1 with already used hash
await bridgeRelayer.setMode(6);
// Sync withheld once with the correct nonce
await wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload, {value: defaultMsgValue});
await wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload, {value: defaultMsgValue});
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"],
[deployer.address, defaultGasLimit]);
// Need to create a withheld condition again by sending another staking to a wrong address
Expand All @@ -1077,7 +1077,7 @@ describe("StakingBridging", async () => {
// Now the delivery hash will fail
bridgePayload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [deployer.address, 0]);
await expect(
wormholeTargetDispenserL2.syncWithheldTokens(bridgePayload, {value: defaultMsgValue})
wormholeTargetDispenserL2.syncWithheldAmount(bridgePayload, {value: defaultMsgValue})
).to.be.revertedWithCustomError(wormholeTargetDispenserL2, "AlreadyDelivered");
});
});
Expand Down

0 comments on commit acf3e38

Please sign in to comment.