Skip to content

Commit d38d5c7

Browse files
committed
Updated claimHelper address management, added deployment script for implem
1 parent 01a1918 commit d38d5c7

File tree

6 files changed

+120
-37
lines changed

6 files changed

+120
-37
lines changed

contracts/interfaces/IStakedTokenV3.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ interface IStakedTokenV3 is IStakedToken {
5858
uint256 claimAmount,
5959
uint256 redeemAmount
6060
) external;
61+
62+
function setClaimHelper(address claimHelper) external;
63+
64+
function getClaimHelper() external view returns (address);
6165
}

contracts/stake/StakedTokenV3.sol

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,21 @@ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager {
3131
using SafeERC20 for IERC20;
3232
using PercentageMath for uint256;
3333

34-
uint256 public constant SLASH_ADMIN_ROLE = 0;
34+
uint256 public constant MAIN_ADMIN_ROLE = 0;
3535
uint256 public constant COOLDOWN_ADMIN_ROLE = 1;
36-
uint256 public constant CLAIM_HELPER_ROLE = 2;
3736

3837
function REVISION() public pure virtual override returns (uint256) {
39-
return 3;
38+
return 6;
4039
}
4140

4241
//maximum percentage of the underlying that can be slashed in a single realization event
4342
uint256 internal _maxSlashablePercentage;
4443
bool _cooldownPaused;
4544

46-
modifier onlySlashingAdmin {
47-
require(msg.sender == getAdmin(SLASH_ADMIN_ROLE), 'CALLER_NOT_SLASHING_ADMIN');
45+
address internal _claimHelper;
46+
47+
modifier onlyAdmin {
48+
require(msg.sender == getAdmin(MAIN_ADMIN_ROLE), 'CALLER_NOT_MAIN_ADMIN');
4849
_;
4950
}
5051

@@ -54,7 +55,7 @@ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager {
5455
}
5556

5657
modifier onlyClaimHelper {
57-
require(msg.sender == getAdmin(CLAIM_HELPER_ROLE), 'CALLER_NOT_CLAIM_HELPER');
58+
require(msg.sender == _claimHelper, 'CALLER_NOT_CLAIM_HELPER');
5859
_;
5960
}
6061

@@ -142,18 +143,17 @@ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager {
142143
_setupDecimals(decimals);
143144
}
144145

145-
address[] memory adminsAddresses = new address[](3);
146-
uint256[] memory adminsRoles = new uint256[](3);
146+
address[] memory adminsAddresses = new address[](2);
147+
uint256[] memory adminsRoles = new uint256[](2);
147148

148149
adminsAddresses[0] = slashingAdmin;
149150
adminsAddresses[1] = cooldownPauseAdmin;
150-
adminsAddresses[2] = claimHelper;
151151

152-
adminsRoles[0] = SLASH_ADMIN_ROLE;
152+
adminsRoles[0] = MAIN_ADMIN_ROLE;
153153
adminsRoles[1] = COOLDOWN_ADMIN_ROLE;
154-
adminsRoles[2] = CLAIM_HELPER_ROLE;
155154

156155
_initAdmins(adminsRoles, adminsAddresses);
156+
_claimHelper = claimHelper;
157157

158158
_maxSlashablePercentage = maxSlashablePercentage;
159159
}
@@ -321,7 +321,7 @@ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager {
321321
* @param destination the address where seized funds will be transferred
322322
* @param amount the amount
323323
**/
324-
function slash(address destination, uint256 amount) external override onlySlashingAdmin {
324+
function slash(address destination, uint256 amount) external override onlyAdmin {
325325
uint256 balance = STAKED_TOKEN.balanceOf(address(this));
326326

327327
uint256 maxSlashable = balance.percentMul(_maxSlashablePercentage);
@@ -333,6 +333,14 @@ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager {
333333
emit Slashed(destination, amount);
334334
}
335335

336+
function setClaimHelper(address claimHelper) external override onlyAdmin {
337+
_claimHelper = claimHelper;
338+
}
339+
340+
function getClaimHelper() external view override returns (address) {
341+
return _claimHelper;
342+
}
343+
336344
/**
337345
* @dev returns true if the unstake cooldown is paused
338346
*/
@@ -353,7 +361,7 @@ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager {
353361
* @dev sets the admin of the slashing pausing function
354362
* @param percentage the new maximum slashable percentage
355363
*/
356-
function setMaxSlashablePercentage(uint256 percentage) external override onlySlashingAdmin {
364+
function setMaxSlashablePercentage(uint256 percentage) external override onlyAdmin {
357365
require(percentage <= PercentageMath.PERCENTAGE_FACTOR, 'INVALID_SLASHING_PERCENTAGE');
358366

359367
_maxSlashablePercentage = percentage;

helpers/constants.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const getAaveTokenPerNetwork = (network: eEthereumNetwork): tEthereumAddr
5151
{
5252
[eEthereumNetwork.coverage]: ZERO_ADDRESS,
5353
[eEthereumNetwork.hardhat]: ZERO_ADDRESS,
54-
[eEthereumNetwork.kovan]: '0xe4483afcf0d612c011679C76B61F5b0d27bAF93C',
54+
[eEthereumNetwork.kovan]: '0xb597cd8d3217ea6477232f9217fa70837ff667af',
5555
[eEthereumNetwork.ropsten]: '0x74dA004A1B81b4d0C79F5820f9FF22647cb1dD95',
5656
[eEthereumNetwork.main]: '0x9c0435779F5E52CEC404D957C9bAa6f7d674C8bA',
5757
},
@@ -63,7 +63,7 @@ export const getCooldownSecondsPerNetwork = (network: eEthereumNetwork): tEthere
6363
{
6464
[eEthereumNetwork.coverage]: COOLDOWN_SECONDS,
6565
[eEthereumNetwork.hardhat]: COOLDOWN_SECONDS,
66-
[eEthereumNetwork.kovan]: '21600', // 8h
66+
[eEthereumNetwork.kovan]: '180', // 5m
6767
[eEthereumNetwork.ropsten]: '180', // 3m
6868
[eEthereumNetwork.main]: '864000', // 10d
6969
},
@@ -87,7 +87,7 @@ export const getAaveAdminPerNetwork = (network: eEthereumNetwork): tEthereumAddr
8787
{
8888
[eEthereumNetwork.coverage]: ZERO_ADDRESS,
8989
[eEthereumNetwork.hardhat]: ZERO_ADDRESS,
90-
[eEthereumNetwork.kovan]: '0x8134929c3dcb1b8b82f27f53424b959fb82182f2', // Aave Governance
90+
[eEthereumNetwork.kovan]: '0x2012b02574f32a96b9cfb8ba7fdfd589d5c70f50', // Short Executor
9191
[eEthereumNetwork.ropsten]: '0xEd93e49A2d75beA505fD4D1A0Dff745f69F2E997', // Aave Governance
9292
[eEthereumNetwork.main]: '0x8a2Efd9A790199F4c94c6effE210fce0B4724f52', // Aave Governance
9393
},
@@ -99,7 +99,8 @@ export const getDistributionDurationPerNetwork = (network: eEthereumNetwork): tE
9999
{
100100
[eEthereumNetwork.coverage]: DISTRIBUTION_DURATION,
101101
[eEthereumNetwork.hardhat]: DISTRIBUTION_DURATION,
102-
[eEthereumNetwork.kovan]: '864000',
102+
// tslint:disable-next-line:max-line-length
103+
[eEthereumNetwork.kovan]: '129600000', // 50 months
103104
[eEthereumNetwork.ropsten]: '864000',
104105
[eEthereumNetwork.main]: '12960000', // 5 months (30 days) in seconds
105106
},
@@ -111,7 +112,7 @@ export const getAaveIncentivesVaultPerNetwork = (network: eEthereumNetwork): tEt
111112
{
112113
[eEthereumNetwork.coverage]: '',
113114
[eEthereumNetwork.hardhat]: '',
114-
[eEthereumNetwork.kovan]: '',
115+
[eEthereumNetwork.kovan]: '0xE8b7fff5035dACa574259dC67FD9639f805edFbf',
115116
[eEthereumNetwork.ropsten]: '',
116117
[eEthereumNetwork.main]: '0x253f7b06c1d60c1fbbc9d82c301327eb86e3ba81',
117118
},
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { task } from 'hardhat/config';
2+
3+
import { eContractid, eEthereumNetwork, tEthereumAddress } from '../../helpers/types';
4+
import { registerContractInJsonDb } from '../../helpers/contracts-helpers';
5+
import {
6+
getAaveTokenPerNetwork,
7+
getCooldownSecondsPerNetwork,
8+
getUnstakeWindowPerNetwork,
9+
getAaveAdminPerNetwork,
10+
getDistributionDurationPerNetwork,
11+
getAaveIncentivesVaultPerNetwork,
12+
ZERO_ADDRESS,
13+
} from '../../helpers/constants';
14+
import { deployStakedAaveV3, deployStakedTokenV3 } from '../../helpers/contracts-accessors';
15+
import { checkVerification, verifyContract } from '../../helpers/etherscan-verification';
16+
17+
const { StakedAave, StakedAaveImpl } = eContractid;
18+
19+
task(`deploy-StakeAave-implementation`, `Deploys the ${StakedAave} V3 implementation contract`)
20+
.addFlag('verify', 'Verify StakedAave contract via Etherscan API.')
21+
.addOptionalParam(
22+
'vaultAddress',
23+
'Use AaveIncentivesVault address by param instead of configuration.'
24+
)
25+
.addOptionalParam('aaveAddress', 'Use AaveToken address by param instead of configuration.')
26+
.setAction(async ({ verify, vaultAddress, aaveAddress }, localBRE) => {
27+
await localBRE.run('set-dre');
28+
29+
if (verify) {
30+
checkVerification();
31+
}
32+
33+
if (!localBRE.network.config.chainId) {
34+
throw new Error('INVALID_CHAIN_ID');
35+
}
36+
37+
const network = localBRE.network.name as eEthereumNetwork;
38+
39+
console.log(`\n- ${StakedAave}-V3 deployment`);
40+
41+
// stakedAAVE V3 and stakedTokenV3 share the same bytecode, they compete when trying to verify.
42+
43+
// NOTE : CONFIG WORKING FOR KOVAN, NOT BEEN VERIFIED FOR MAINNET
44+
console.log(`\tDeploying ${StakedAave} implementation ...`);
45+
const constructorArguments = [
46+
aaveAddress || getAaveTokenPerNetwork(network),
47+
aaveAddress || getAaveTokenPerNetwork(network),
48+
getCooldownSecondsPerNetwork(network),
49+
getUnstakeWindowPerNetwork(network),
50+
vaultAddress || getAaveIncentivesVaultPerNetwork(network),
51+
getAaveAdminPerNetwork(network),
52+
getDistributionDurationPerNetwork(network),
53+
'Staked Aave',
54+
'stkAAVE',
55+
'18',
56+
ZERO_ADDRESS,
57+
] as [string, string, string, string, string, string, string, string, string, string, string];
58+
59+
const stakedAaveImpl = await deployStakedTokenV3(
60+
constructorArguments,
61+
false // disable verify due not supported by current buidler etherscan plugin
62+
);
63+
await stakedAaveImpl.deployTransaction.wait();
64+
await registerContractInJsonDb(StakedAaveImpl, stakedAaveImpl);
65+
66+
if (verify) {
67+
await verifyContract(stakedAaveImpl.address, constructorArguments);
68+
}
69+
70+
console.log(`\tFinished ${StakedAave} proxy and implementation deployment`);
71+
});

test/StakedAaveV3/claimHelper.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ makeSuite('StakedAave V3 Claim Helper', (testEnv: TestEnv) => {
128128
);
129129
const slashingAdmin = await stakeAaveV3.getAdmin(SLASHING_ADMIN); //slash admin
130130
const cooldownAdmin = await stakeAaveV3.getAdmin(COOLDOWN_ADMIN); //cooldown admin
131-
const claimAdmin = await stakeAave2V3.getAdmin(CLAIM_HELPER_ROLE); //claim admin // helper contract
131+
const claimAdmin = await stakeAave2V3.getClaimHelper(); //claim admin // helper contract
132132
const slashingAdmin2 = await stakeAave2V3.getAdmin(SLASHING_ADMIN); //slash admin
133133
const cooldownAdmin2 = await stakeAave2V3.getAdmin(COOLDOWN_ADMIN); //cooldown admin
134-
const claimAdmin2 = await stakeAave2V3.getAdmin(CLAIM_HELPER_ROLE); //claim admin // helper contract
134+
const claimAdmin2 = await stakeAave2V3.getClaimHelper(); //claim admin // helper contract
135135

136136
expect(slashingAdmin).to.be.equal(users[0].address);
137137
expect(cooldownAdmin).to.be.equal(users[1].address);

test/StakedAaveV3/stakedAave-V3.spec.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ makeSuite('StakedAave V3 slashing tests', (testEnv: TestEnv) => {
7070

7171
const slashingAdmin = await stakeV3.getAdmin(SLASHING_ADMIN); //slash admin
7272
const cooldownAdmin = await stakeV3.getAdmin(COOLDOWN_ADMIN); //cooldown admin
73-
const claimAdmin = await stakeV3.getAdmin(CLAIM_HELPER_ROLE); //claim admin // helper contract
73+
const claimAdmin = await stakeV3.getClaimHelper(); //claim admin // helper contract
7474

7575
expect(slashingAdmin).to.be.equal(users[0].address);
7676
expect(cooldownAdmin).to.be.equal(users[1].address);
@@ -86,6 +86,7 @@ makeSuite('StakedAave V3 slashing tests', (testEnv: TestEnv) => {
8686
await expect(stakeV3.connect(staker.signer).stake(staker.address, amount)).to.be.revertedWith(
8787
'INVALID_ZERO_AMOUNT'
8888
);
89+
console.log((await stakeV3.balanceOf(staker.address)).toString());
8990
});
9091

9192
it('User 1 stakes 10 AAVE: receives 10 stkAAVE, StakedAave balance of AAVE is 10 and his rewards to claim are 0', async () => {
@@ -353,9 +354,7 @@ makeSuite('StakedAave V3 slashing tests', (testEnv: TestEnv) => {
353354
it('Tries to slash with an account that is not the slashing admin', async () => {
354355
const { users } = testEnv;
355356

356-
await expect(stakeV3.slash(users[2].address, '1')).to.be.revertedWith(
357-
'CALLER_NOT_SLASHING_ADMIN'
358-
);
357+
await expect(stakeV3.slash(users[2].address, '1')).to.be.revertedWith('CALLER_NOT_MAIN_ADMIN');
359358
});
360359

361360
it('Tries to pause the cooldown with an account that is not the cooldown admin', async () => {
@@ -583,10 +582,7 @@ makeSuite('StakedAave V3 slashing tests', (testEnv: TestEnv) => {
583582
balanceBefore.add(amount.mul(ether).div(exchangeRate))
584583
);
585584

586-
expect(aaveStakedAfter).to.be.eql(
587-
aaveStakedBefore.add(amount)
588-
);
589-
585+
expect(aaveStakedAfter).to.be.eql(aaveStakedBefore.add(amount));
590586
});
591587
it('Fails claim rewards for someone using claimRewardsOnBehalf if not helper', async () => {
592588
const {
@@ -718,17 +714,20 @@ makeSuite('StakedAave V3 slashing tests', (testEnv: TestEnv) => {
718714
await stakeV3.balanceOf(staker.address),
719715
];
720716

717+
expect(userBalanceAfterActions[0]).to.be.eq(
718+
saveUserBalance[0],
719+
'Invalid aave user balance after action'
720+
);
721721

722-
expect(userBalanceAfterActions[0]).to.be.eq(saveUserBalance[0], "Invalid aave user balance after action");
723-
724-
expect(
725-
userBalanceAfterActions[1]
726-
).to.be.eq(
727-
saveUserBalance[1].add(halfRewards.mul(ether).div(currentExchangeRate))
728-
,"invalid stkAAVE user balance after action")
722+
expect(userBalanceAfterActions[1]).to.be.eq(
723+
saveUserBalance[1].add(halfRewards.mul(ether).div(currentExchangeRate)),
724+
'invalid stkAAVE user balance after action'
725+
);
729726

730-
expect(aaveStakedAfter).to.be.equal(aaveStakedBefore.add(halfRewards), "Invalid underlying balance");
731-
727+
expect(aaveStakedAfter).to.be.equal(
728+
aaveStakedBefore.add(halfRewards),
729+
'Invalid underlying balance'
730+
);
732731
});
733732
it('Claim & stake higher reward than current rewards balance', async () => {
734733
const {

0 commit comments

Comments
 (0)