Skip to content

Commit

Permalink
Merge branch 'contracts/AdvancedStakeActionMsgTranslator' into 'main'
Browse files Browse the repository at this point in the history
feat(contracts): add Adv stake msg translator

See merge request pantherprotocol/panther-core!1017
  • Loading branch information
vkonst committed Apr 15, 2023
2 parents c131cb9 + a49ea2f commit 8187393
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 0 deletions.
3 changes: 3 additions & 0 deletions contracts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ PANTHER_POOL_V0_IMP_POLYGON=
PNFT_TOKEN_POLYGON=
ADVANCED_STAKE_REWARD_CONTROLLER_POLYGON=
ADVANCED_STAKE_ACTION_MSG_RELAYER_PROXY_POLYGON=
ADVANCED_STAKE_V2_ACTION_MSG_TRANSLATOR_POLYGON=



Expand All @@ -59,6 +60,8 @@ ADVANCED_STAKE_ACTION_MSG_RELAYER_PROXY_POLYGON=
ZKP_TOKEN_MUMBAI=0x3F73371cFA58F338C479928AC7B4327478Cb859f
ZKP_FAUCET_MUMBAI=0xB79A02672bb45B5fFBE907b2aD1A5Ab84e151EC6
ADVANCED_STAKE_ACTION_MSG_RELAYER_PROXY_MUMBAI=
ADVANCED_STAKE_ACTION_MSG_TRANSLATOR_MUMBAI=



# Hardhat private key (Account #0)
Expand Down
65 changes: 65 additions & 0 deletions contracts/contracts/staking/AdvancedStakeV2ActionMsgTranslator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: Copyright 2023 Panther Ventures Limited Gibraltar
pragma solidity 0.8.16;

import "./interfaces/IRewardAdviser.sol";
import "./interfaces/IActionMsgReceiver.sol";
import { ADVANCED_STAKE, ADVANCED_STAKE_V2, ADVANCED_UNSTAKE_V2 } from "./actions/Constants.sol";

/**
* @title AdvancedStakeV2ActionMsgTranslator
* @notice It processes action messages for stakes of the `advanced-v2` type.
* @dev It "translates" the `action` in messages so that other contracts, which
* are "unaware" of "v2" stake type, may process this type stakes exactly like
* they process `advanced` type stakes.
* It shall be registered with the `RewardMaster` as the "RewardAdviser" for
* `advanced-v2` type stakes and the "ActionOracle" for `advanced` type stakes.
* Being called `getRewardAdvice` by the RewardMaster for a message with the
* `advanced-v2` STAKE action, it replaces the `action` to be the `advanced`
* (but not `advanced-v2`) STAKE action.
* Then it calls `onAction` on the RewardMaster with the substituted message.
* When called back, the latter processes the substituted action message as if
* it is the `advanced` (not `advanced-v2`) STAKE action.
*/
contract AdvancedStakeV2ActionMsgTranslator is IRewardAdviser {
// solhint-disable var-name-mixedcase

/// @notice RewardMaster contract instance
address private immutable REWARD_MASTER;

// solhint-enable var-name-mixedcase

constructor(address rewardMaster) {
require(rewardMaster != address(0), "Zero address");

REWARD_MASTER = rewardMaster;
}

/// @dev To be called by the {RewardMaster} for `advanced-v2` type actions.
/// It makes the `action` to look like the `advanced` (not "v2") type action
/// and calls the {RewardMaster} back simulating a "new" action message.
function getRewardAdvice(bytes4 action, bytes memory message)
external
override
returns (Advice memory)
{
require(msg.sender == REWARD_MASTER, "AMT: unauthorized");

if (action == ADVANCED_STAKE_V2) {
// Replace the action and return the message back to REWARD_MASTER
IActionMsgReceiver(REWARD_MASTER).onAction(ADVANCED_STAKE, message);
} else {
require(action == ADVANCED_UNSTAKE_V2, "AMT: unsupported action");
}

// Return "zero" advice
return
Advice(
address(0), // createSharesFor
0, // sharesToCreate
address(0), // redeemSharesFrom
0, // sharesToRedeem
address(0) // sendRewardTo
);
}
}
12 changes: 12 additions & 0 deletions contracts/contracts/staking/actions/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ bytes4 constant ADVANCED_STAKE = 0xcc995ce8;
// bytes4(keccak256(abi.encodePacked(bytes4(keccak256("unstake"), ADVANCED_STAKE_TYPE)))
bytes4 constant ADVANCED_UNSTAKE = 0xb8372e55;

// The "stake type" for the "advance staking"
// bytes4(keccak256("advanced-v2"))
bytes4 constant ADVANCED_STAKE_V2_TYPE = 0x8496de05;

// STAKE "action type" for the "advanced staking V2"
// bytes4(keccak256(abi.encodePacked(bytes4(keccak256("stake"), ADVANCED_STAKE_V2_TYPE)))
bytes4 constant ADVANCED_STAKE_V2 = 0x1954e321;

// UNSTAKE "action type" for the "advanced staking v2"
// bytes4(keccak256(abi.encodePacked(bytes4(keccak256("unstake"), ADVANCED_STAKE_V2_TYPE)))
bytes4 constant ADVANCED_UNSTAKE_V2 = 0x6a8ecb81;

// PRP grant type for the "advanced" stake
// bytes4(keccak256("forAdvancedStakeGrant"))
bytes4 constant FOR_ADVANCED_STAKE_GRANT = 0x31a180d4;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import {DeployFunction} from 'hardhat-deploy/types';

import {
reuseEnvAddress,
getContractAddress,
verifyUserConsentOnProd,
} from '../../lib/deploymentHelpers';

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const {deployments, getNamedAccounts} = hre;
const {deploy} = deployments;
const {deployer} = await getNamedAccounts();

await verifyUserConsentOnProd(hre, deployer);

if (reuseEnvAddress(hre, 'ADVANCED_STAKE_V2_ACTION_MSG_TRANSLATOR')) return;

const rewardMaster = await getContractAddress(
hre,
'RewardMaster',
'REWARD_MASTER',
);

await deploy('AdvancedStakeActionMsgTranslator', {
from: deployer,
args: [rewardMaster],
log: true,
autoMine: true,
});
};

export default func;

func.tags = ['advanced-staking', 'advanced-stake-v2-action-translator'];
func.dependencies = ['check-params', 'reward-master'];
43 changes: 43 additions & 0 deletions contracts/test/staking/advancedStakeV2ActionMsgTranslator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {expect} from 'chai';
import hardhat from 'hardhat';

const {ethers} = hardhat;

import {AdvancedStakeV2ActionMsgTranslator} from '../../types/contracts';

describe('AdvancedStakeV2ActionMsgTranslator', () => {
const advStakeV2 = '0x1954e321';
const invalidAction = '0x12345678';
const message = '0x00';

let translator: AdvancedStakeV2ActionMsgTranslator;
let user: SignerWithAddress;
let rewardMaster: SignerWithAddress;

before(async () => {
[user, rewardMaster] = await ethers.getSigners();

const AdvancedStakeV2ActionMsgTranslator =
await ethers.getContractFactory(
'AdvancedStakeV2ActionMsgTranslator',
);
translator = (await AdvancedStakeV2ActionMsgTranslator.deploy(
rewardMaster.address,
)) as AdvancedStakeV2ActionMsgTranslator;
});

it('should throw when executed by unauthorized account', async () => {
await expect(
translator.connect(user).getRewardAdvice(advStakeV2, message),
).to.be.revertedWith('AMT: unauthorized');
});

it('should throw when executed with invalid action type', async () => {
await expect(
translator
.connect(rewardMaster)
.getRewardAdvice(invalidAction, message),
).to.be.revertedWith('AMT: unsupported action');
});
});

0 comments on commit 8187393

Please sign in to comment.