Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/gov/Executor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@aave/governance-v2/contracts/governance/Executor.sol';
106 changes: 1 addition & 105 deletions contracts/interfaces/IAaveGovernanceV2.sol
Original file line number Diff line number Diff line change
@@ -1,105 +1 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.7.5;
pragma abicoder v2;

// simplified interface to expose functions added events for tests
interface IAaveGovernanceV2 {
struct Vote {
bool support;
uint248 votingPower;
}

/**
Added for test purposes
**/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
enum ProposalState {Pending, Canceled, Active, Failed, Succeeded, Queued, Expired, Executed}

/**
* @dev Creates a Proposal (needs Proposition Power of creator > Threshold)
* @param executor The ExecutorWithTimelock contract that will execute the proposal
* @param targets list of contracts called by proposal's associated transactions
* @param values list of value in wei for each propoposal's associated transaction
* @param signatures list of function signatures (can be empty) to be used when created the callData
* @param calldatas list of calldatas: if associated signature empty, calldata ready, else calldata is arguments
* @param withDelegatecalls if true, transaction delegatecalls the taget, else calls the target
* @param ipfsHash IPFS hash of the proposal
**/
function create(
address executor,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
bool[] memory withDelegatecalls,
bytes32 ipfsHash
) external returns (uint256);

/**
* @dev Cancels a Proposal,
* either at anytime by guardian
* or when proposal is Pending/Active and threshold no longer reached
* @param proposalId id of the proposal
**/
function cancel(uint256 proposalId) external;

/**
* @dev Queue the proposal (If Proposal Succeeded)
* @param proposalId id of the proposal to queue
**/
function queue(uint256 proposalId) external;

/**
* @dev Execute the proposal (If Proposal Queued)
* @param proposalId id of the proposal to execute
**/
function execute(uint256 proposalId) external payable;

/**
* @dev Function allowing msg.sender to vote for/against a proposal
* @param proposalId id of the proposal
* @param support boolean, true = vote for, false = vote against
**/
function submitVote(uint256 proposalId, bool support) external;

/**
* @dev Function to register the vote of user that has voted offchain via signature
* @param proposalId id of the proposal
* @param support boolean, true = vote for, false = vote against
* @param v v part of the voter signature
* @param r r part of the voter signature
* @param s s part of the voter signature
**/
function submitVoteBySignature(
uint256 proposalId,
bool support,
uint8 v,
bytes32 r,
bytes32 s
) external;

/**
* @dev Getter of the proposal count (the current number of proposals ever created)
* @return the proposal count
**/
function getProposalsCount() external view returns (uint256);

function getProposalState(uint256 proposalId) external view returns (ProposalState);

function getGuardian() external view returns (address);

/**
* @dev Getter of the Vote of a voter about a proposal
* Note: Vote is a struct: ({bool support, uint248 votingPower})
* @param proposalId id of the proposal
* @param voter address of the voter
* @return The associated Vote memory object
**/
function getVoteOnProposal(uint256 proposalId, address voter) external view returns (Vote memory);
}
import '@aave/governance-v2/contracts/interfaces/IAaveGovernanceV2.sol';
11 changes: 11 additions & 0 deletions contracts/interfaces/IBaseAdminUpgradabilityProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pragma solidity ^0.7.5;

interface IBaseAdminUpgradabilityProxy {
function upgradeTo(address newImplementation) external;

function implementation() external returns (address);

function admin() external returns (address);

function changeAdmin(address newAdmin) external;
}
4 changes: 4 additions & 0 deletions contracts/interfaces/IStakedTokenV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ interface IStakedTokenV3 is IStakedToken {

function setCooldownPause(bool paused) external;

function getEmergencyShutdown() external view returns (bool);

function setEmergencyShutdown(bool emergencyShutdown) external;

function slash(address destination, uint256 amount) external;

function getMaxSlashablePercentage() external view returns (uint256);
Expand Down
21 changes: 21 additions & 0 deletions contracts/proposals/StakeTokenUpgradeProposal.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.7.5;
pragma abicoder v2;

import {IBaseAdminUpgradabilityProxy} from './../interfaces/IBaseAdminUpgradabilityProxy.sol';

contract StakeTokenUpgradeProposalExecutor {
// TODO: Replace with constant address when implementation is deployed
address immutable NEW_STAKED_AAVE_TOKEN_IMPLEMENTATION;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems clearer to fix the address here directly (instead of using the constructor)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be fixed when we have an implementation that is deployed.
Using the constructor for passing freshly deployed implementation made testing easier.


constructor(address newStakedAaveTokenImplementation) {
NEW_STAKED_AAVE_TOKEN_IMPLEMENTATION = newStakedAaveTokenImplementation;
}

IBaseAdminUpgradabilityProxy constant STAKED_AAVE_TOKEN_PROXY =
IBaseAdminUpgradabilityProxy(0x4da27a545c0c5B758a6BA100e3a049001de870f5);

function execute() external {
STAKED_AAVE_TOKEN_PROXY.upgradeTo(NEW_STAKED_AAVE_TOKEN_IMPLEMENTATION);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should initialize, so upgradeToAndCall

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Is updated in the newest commit.

}
}
66 changes: 37 additions & 29 deletions contracts/stake/StakedTokenV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,12 @@ contract StakedTokenV2 is
require(amount != 0, 'INVALID_ZERO_AMOUNT');
uint256 balanceOfUser = balanceOf(onBehalfOf);

uint256 accruedRewards =
_updateUserAssetInternal(onBehalfOf, address(this), balanceOfUser, totalSupply());
uint256 accruedRewards = _updateUserAssetInternal(
onBehalfOf,
address(this),
balanceOfUser,
totalSupply()
);
if (accruedRewards != 0) {
emit RewardsAccrued(onBehalfOf, accruedRewards);
stakerRewardsToClaim[onBehalfOf] = stakerRewardsToClaim[onBehalfOf].add(accruedRewards);
Expand Down Expand Up @@ -175,7 +179,7 @@ contract StakedTokenV2 is
* @dev Activates the cooldown period to unstake
* - It can't be called if the user is not staking
**/
function cooldown() external override {
function cooldown() external virtual override {
require(balanceOf(msg.sender) != 0, 'INVALID_BALANCE_ON_COOLDOWN');
//solium-disable-next-line
stakersCooldowns[msg.sender] = block.timestamp;
Expand All @@ -189,8 +193,11 @@ contract StakedTokenV2 is
* @param amount Amount to stake
**/
function claimRewards(address to, uint256 amount) external virtual override {
uint256 newTotalRewards =
_updateCurrentUnclaimedRewards(msg.sender, balanceOf(msg.sender), false);
uint256 newTotalRewards = _updateCurrentUnclaimedRewards(
msg.sender,
balanceOf(msg.sender),
false
);
uint256 amountToClaim = (amount == type(uint256).max) ? newTotalRewards : amount;

stakerRewardsToClaim[msg.sender] = newTotalRewards.sub(amountToClaim, 'INVALID_AMOUNT');
Expand Down Expand Up @@ -248,8 +255,12 @@ contract StakedTokenV2 is
uint256 userBalance,
bool updateStorage
) internal returns (uint256) {
uint256 accruedRewards =
_updateUserAssetInternal(user, address(this), userBalance, totalSupply());
uint256 accruedRewards = _updateUserAssetInternal(
user,
address(this),
userBalance,
totalSupply()
);
uint256 unclaimedRewards = stakerRewardsToClaim[user].add(accruedRewards);

if (accruedRewards != 0) {
Expand Down Expand Up @@ -287,24 +298,23 @@ contract StakedTokenV2 is
return 0;
}

uint256 minimalValidCooldownTimestamp =
block.timestamp.sub(COOLDOWN_SECONDS).sub(UNSTAKE_WINDOW);
uint256 minimalValidCooldownTimestamp = block.timestamp.sub(COOLDOWN_SECONDS).sub(
UNSTAKE_WINDOW
);

if (minimalValidCooldownTimestamp > toCooldownTimestamp) {
toCooldownTimestamp = 0;
} else {
uint256 fromCooldownTimestamp =
(minimalValidCooldownTimestamp > fromCooldownTimestamp)
? block.timestamp
: fromCooldownTimestamp;
uint256 fromCooldownTimestamp = (minimalValidCooldownTimestamp > fromCooldownTimestamp)
? block.timestamp
: fromCooldownTimestamp;

if (fromCooldownTimestamp < toCooldownTimestamp) {
return toCooldownTimestamp;
} else {
toCooldownTimestamp = (
amountToReceive.mul(fromCooldownTimestamp).add(toBalance.mul(toCooldownTimestamp))
)
.div(amountToReceive.add(toBalance));
).div(amountToReceive.add(toBalance));
}
}
return toCooldownTimestamp;
Expand All @@ -316,8 +326,8 @@ contract StakedTokenV2 is
* @return The rewards
*/
function getTotalRewardsBalance(address staker) external view returns (uint256) {
DistributionTypes.UserStakeInput[] memory userStakeInputs =
new DistributionTypes.UserStakeInput[](1);
DistributionTypes.UserStakeInput[]
memory userStakeInputs = new DistributionTypes.UserStakeInput[](1);
userStakeInputs[0] = DistributionTypes.UserStakeInput({
underlyingAsset: address(this),
stakedByUser: balanceOf(staker),
Expand Down Expand Up @@ -358,14 +368,13 @@ contract StakedTokenV2 is
//solium-disable-next-line
require(block.timestamp <= deadline, 'INVALID_EXPIRATION');
uint256 currentValidNonce = _nonces[owner];
bytes32 digest =
keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
)
);
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
)
);

require(owner == ecrecover(digest, v, r, s), 'INVALID_SIGNATURE');
_nonces[owner] = currentValidNonce.add(1);
Expand Down Expand Up @@ -467,10 +476,9 @@ contract StakedTokenV2 is
bytes32 r,
bytes32 s
) public {
bytes32 structHash =
keccak256(
abi.encode(DELEGATE_BY_TYPE_TYPEHASH, delegatee, uint256(delegationType), nonce, expiry)
);
bytes32 structHash = keccak256(
abi.encode(DELEGATE_BY_TYPE_TYPEHASH, delegatee, uint256(delegationType), nonce, expiry)
);
bytes32 digest = keccak256(abi.encodePacked('\x19\x01', DOMAIN_SEPARATOR, structHash));
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), 'INVALID_SIGNATURE');
Expand Down
Loading