From 43c8ef02dbcfae1fbbbde572345ecd54637108d1 Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 16:53:20 +0300 Subject: [PATCH 1/8] initial integration of pei, no tests --- .../interfaces/IAaveIncentivesController.sol | 11 +++++ contracts/mocks/upgradeability/MockAToken.sol | 5 ++- .../upgradeability/MockStableDebtToken.sol | 8 +++- .../upgradeability/MockVariableDebtToken.sol | 14 ++++++- contracts/tokenization/AToken.sol | 20 ++++++++- contracts/tokenization/ERC20.sol | 41 ++++++++++++++++--- contracts/tokenization/StableDebtToken.sol | 5 ++- contracts/tokenization/VariableDebtToken.sol | 5 ++- contracts/tokenization/base/DebtTokenBase.sol | 5 ++- contracts/tokenization/interfaces/IAToken.sol | 8 ++++ 10 files changed, 102 insertions(+), 20 deletions(-) create mode 100644 contracts/interfaces/IAaveIncentivesController.sol diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol new file mode 100644 index 00000000..83f1769c --- /dev/null +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.8; +pragma experimental ABIEncoderV2; + +interface IAaveIncentivesController { + function handleAction( + address user, + uint256 userBalance, + uint256 totalSupply + ) external; +} diff --git a/contracts/mocks/upgradeability/MockAToken.sol b/contracts/mocks/upgradeability/MockAToken.sol index 05f0db4e..f84543d9 100644 --- a/contracts/mocks/upgradeability/MockAToken.sol +++ b/contracts/mocks/upgradeability/MockAToken.sol @@ -9,8 +9,9 @@ contract MockAToken is AToken { LendingPool _pool, address _underlyingAssetAddress, string memory _tokenName, - string memory _tokenSymbol - ) public AToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {} + string memory _tokenSymbol, + address incentivesController + ) public AToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController) {} function getRevision() internal override pure returns (uint256) { return 0x2; diff --git a/contracts/mocks/upgradeability/MockStableDebtToken.sol b/contracts/mocks/upgradeability/MockStableDebtToken.sol index 52e7a99f..6f44cf07 100644 --- a/contracts/mocks/upgradeability/MockStableDebtToken.sol +++ b/contracts/mocks/upgradeability/MockStableDebtToken.sol @@ -9,8 +9,12 @@ contract MockStableDebtToken is StableDebtToken { address _pool, address _underlyingAssetAddress, string memory _tokenName, - string memory _tokenSymbol - ) public StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {} + string memory _tokenSymbol, + address incentivesController + ) + public + StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController) + {} function getRevision() internal override pure returns (uint256) { return 0x2; diff --git a/contracts/mocks/upgradeability/MockVariableDebtToken.sol b/contracts/mocks/upgradeability/MockVariableDebtToken.sol index cb46d4d8..4e4a7ffa 100644 --- a/contracts/mocks/upgradeability/MockVariableDebtToken.sol +++ b/contracts/mocks/upgradeability/MockVariableDebtToken.sol @@ -9,8 +9,18 @@ contract MockVariableDebtToken is VariableDebtToken { address _pool, address _underlyingAssetAddress, string memory _tokenName, - string memory _tokenSymbol - ) public VariableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {} + string memory _tokenSymbol, + address incentivesController + ) + public + VariableDebtToken( + _pool, + _underlyingAssetAddress, + _tokenName, + _tokenSymbol, + incentivesController + ) + {} function getRevision() internal override pure returns (uint256) { return 0x2; diff --git a/contracts/tokenization/AToken.sol b/contracts/tokenization/AToken.sol index c2924d3d..3c248fdb 100644 --- a/contracts/tokenization/AToken.sol +++ b/contracts/tokenization/AToken.sol @@ -45,8 +45,9 @@ contract AToken is VersionedInitializable, ERC20, IAToken { LendingPool pool, address underlyingAssetAddress, string memory tokenName, - string memory tokenSymbol - ) public ERC20(tokenName, tokenSymbol, 18) { + string memory tokenSymbol, + address incentivesController + ) public ERC20(tokenName, tokenSymbol, 18, incentivesController) { POOL = pool; UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress; } @@ -161,6 +162,21 @@ contract AToken is VersionedInitializable, ERC20, IAToken { return super.balanceOf(user); } + /** + * @dev returns the principal balance of the user and principal total supply. + * @param user the address of the user + * @return the principal balance of the user + * @return the principal total supply + **/ + function getScaledUserBalanceAndSupply(address user) + external + override + view + returns (uint256, uint256) + { + return (super.balanceOf(user), super.totalSupply()); + } + /** * @dev calculates the total supply of the specific aToken * since the balance of every single user increases over time, the total supply diff --git a/contracts/tokenization/ERC20.sol b/contracts/tokenization/ERC20.sol index f2902ce4..91194087 100644 --- a/contracts/tokenization/ERC20.sol +++ b/contracts/tokenization/ERC20.sol @@ -5,6 +5,7 @@ import {Context} from '../misc/Context.sol'; import {IERC20} from '../interfaces/IERC20.sol'; import {IERC20Detailed} from '../interfaces/IERC20Detailed.sol'; import {SafeMath} from '../libraries/math/SafeMath.sol'; +import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol'; /** * @title ERC20 @@ -14,6 +15,8 @@ import {SafeMath} from '../libraries/math/SafeMath.sol'; contract ERC20 is Context, IERC20, IERC20Detailed { using SafeMath for uint256; + IAaveIncentivesController internal immutable _incentivesController; + mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; @@ -24,11 +27,13 @@ contract ERC20 is Context, IERC20, IERC20Detailed { constructor( string memory name, string memory symbol, - uint8 decimals + uint8 decimals, + address incentivesController ) public { _name = name; _symbol = symbol; _decimals = decimals; + _incentivesController = IAaveIncentivesController(incentivesController); } /** @@ -167,8 +172,16 @@ contract ERC20 is Context, IERC20, IERC20Detailed { _beforeTokenTransfer(sender, recipient, amount); - _balances[sender] = _balances[sender].sub(amount, 'ERC20: transfer amount exceeds balance'); + uint256 oldSenderBalance = _balances[sender]; + _balances[sender] = oldSenderBalance.sub(amount, 'ERC20: transfer amount exceeds balance'); + uint256 oldRecipientBalance = _balances[recipient]; _balances[recipient] = _balances[recipient].add(amount); + + if (address(_incentivesController) != address(0x0)) { + uint256 totalSupply = _totalSupply; + _incentivesController.handleAction(sender, totalSupply, oldSenderBalance); + _incentivesController.handleAction(recipient, totalSupply, oldRecipientBalance); + } emit Transfer(sender, recipient, amount); } @@ -177,8 +190,16 @@ contract ERC20 is Context, IERC20, IERC20Detailed { _beforeTokenTransfer(address(0), account, amount); - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); + uint256 oldTotalSupply = _totalSupply; + _totalSupply = oldTotalSupply.add(amount); + + uint256 oldAccountBalance = _balances[account]; + _balances[account] = oldAccountBalance.add(amount); + + if (address(_incentivesController) != address(0x0)) { + _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); + } + emit Transfer(address(0), account, amount); } @@ -187,8 +208,16 @@ contract ERC20 is Context, IERC20, IERC20Detailed { _beforeTokenTransfer(account, address(0), amount); - _balances[account] = _balances[account].sub(amount, 'ERC20: burn amount exceeds balance'); - _totalSupply = _totalSupply.sub(amount); + uint256 oldTotalSupply = _totalSupply; + _totalSupply = oldTotalSupply.sub(amount); + + uint256 oldAccountBalance = _balances[account]; + _balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance'); + + if (address(_incentivesController) != address(0x0)) { + _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); + } + emit Transfer(account, address(0), amount); } diff --git a/contracts/tokenization/StableDebtToken.sol b/contracts/tokenization/StableDebtToken.sol index 8e5da21b..fd2affca 100644 --- a/contracts/tokenization/StableDebtToken.sol +++ b/contracts/tokenization/StableDebtToken.sol @@ -26,8 +26,9 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { address pool, address underlyingAsset, string memory name, - string memory symbol - ) public DebtTokenBase(pool, underlyingAsset, name, symbol) {} + string memory symbol, + address incentivesController + ) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {} /** * @dev gets the revision of the stable debt token implementation diff --git a/contracts/tokenization/VariableDebtToken.sol b/contracts/tokenization/VariableDebtToken.sol index e52f7c61..879ffc17 100644 --- a/contracts/tokenization/VariableDebtToken.sol +++ b/contracts/tokenization/VariableDebtToken.sol @@ -22,8 +22,9 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { address pool, address underlyingAsset, string memory name, - string memory symbol - ) public DebtTokenBase(pool, underlyingAsset, name, symbol) {} + string memory symbol, + address incentivesController + ) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {} /** * @dev gets the revision of the stable debt token implementation diff --git a/contracts/tokenization/base/DebtTokenBase.sol b/contracts/tokenization/base/DebtTokenBase.sol index a6bd4005..f09e92d4 100644 --- a/contracts/tokenization/base/DebtTokenBase.sol +++ b/contracts/tokenization/base/DebtTokenBase.sol @@ -38,8 +38,9 @@ abstract contract DebtTokenBase is ERC20, VersionedInitializable { address pool, address underlyingAssetAddress, string memory name, - string memory symbol - ) public ERC20(name, symbol, 18) { + string memory symbol, + address incentivesController + ) public ERC20(name, symbol, 18, incentivesController) { POOL = ILendingPool(pool); UNDERLYING_ASSET = underlyingAssetAddress; } diff --git a/contracts/tokenization/interfaces/IAToken.sol b/contracts/tokenization/interfaces/IAToken.sol index 873860a9..e1975074 100644 --- a/contracts/tokenization/interfaces/IAToken.sol +++ b/contracts/tokenization/interfaces/IAToken.sol @@ -82,6 +82,14 @@ interface IAToken is IERC20 { **/ function scaledBalanceOf(address user) external view returns (uint256); + /** + * @dev returns the principal balance of the user and principal total supply. + * @param user the address of the user + * @return the principal balance of the user + * @return the principal total supply + **/ + function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); + /** * @dev Used to validate transfers before actually executing them. * @param user address of the user to check From 84cf68e58ef464a7c229c1e074cbc9468512de99 Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 17:02:21 +0300 Subject: [PATCH 2/8] fix deployment and tests --- helpers/contracts-helpers.ts | 78 ++++++++++++++++++------------------ test/__setup.spec.ts | 9 ++++- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 2f46cf71..9179aa21 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -32,8 +32,8 @@ import {Ierc20Detailed} from '../types/Ierc20Detailed'; import {StableDebtToken} from '../types/StableDebtToken'; import {VariableDebtToken} from '../types/VariableDebtToken'; import {MockSwapAdapter} from '../types/MockSwapAdapter'; -import { signTypedData_v4, TypedData } from "eth-sig-util"; -import { fromRpcSig, ECDSASignature } from "ethereumjs-util"; +import {signTypedData_v4, TypedData} from 'eth-sig-util'; +import {fromRpcSig, ECDSASignature} from 'ethereumjs-util'; export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => { const currentNetwork = BRE.network.name; @@ -251,49 +251,55 @@ export const deployDefaultReserveInterestRateStrategy = async ([ ] ); -export const deployStableDebtToken = async ([name, symbol, underlyingAsset, poolAddress]: [ - string, - string, - tEthereumAddress, - tEthereumAddress -]) => { +export const deployStableDebtToken = async ([ + name, + symbol, + underlyingAsset, + poolAddress, + incentivesController, +]: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress]) => { const token = await deployContract(eContractid.StableDebtToken, [ poolAddress, underlyingAsset, name, symbol, + incentivesController, ]); return token; }; -export const deployVariableDebtToken = async ([name, symbol, underlyingAsset, poolAddress]: [ - string, - string, - tEthereumAddress, - tEthereumAddress -]) => { +export const deployVariableDebtToken = async ([ + name, + symbol, + underlyingAsset, + poolAddress, + incentivesController, +]: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress]) => { const token = await deployContract(eContractid.VariableDebtToken, [ poolAddress, underlyingAsset, name, symbol, + incentivesController, ]); return token; }; -export const deployGenericAToken = async ([poolAddress, underlyingAssetAddress, name, symbol]: [ - tEthereumAddress, - tEthereumAddress, - string, - string -]) => { +export const deployGenericAToken = async ([ + poolAddress, + underlyingAssetAddress, + name, + symbol, + incentivesController, +]: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress]) => { const token = await deployContract(eContractid.AToken, [ poolAddress, underlyingAssetAddress, name, symbol, + incentivesController, ]); return token; @@ -491,20 +497,20 @@ export const buildPermitParams = ( ) => ({ types: { EIP712Domain: [ - { name: "name", type: "string" }, - { name: "version", type: "string" }, - { name: "chainId", type: "uint256" }, - { name: "verifyingContract", type: "address" }, + {name: 'name', type: 'string'}, + {name: 'version', type: 'string'}, + {name: 'chainId', type: 'uint256'}, + {name: 'verifyingContract', type: 'address'}, ], Permit: [ - { name: "owner", type: "address" }, - { name: "spender", type: "address" }, - { name: "value", type: "uint256" }, - { name: "nonce", type: "uint256" }, - { name: "deadline", type: "uint256" }, + {name: 'owner', type: 'address'}, + {name: 'spender', type: 'address'}, + {name: 'value', type: 'uint256'}, + {name: 'nonce', type: 'uint256'}, + {name: 'deadline', type: 'uint256'}, ], }, - primaryType: "Permit" as const, + primaryType: 'Permit' as const, domain: { name: tokenName, version: revision, @@ -520,16 +526,12 @@ export const buildPermitParams = ( }, }); - export const getSignatureFromTypedData = ( privateKey: string, typedData: any // TODO: should be TypedData, from eth-sig-utils, but TS doesn't accept it ): ECDSASignature => { - const signature = signTypedData_v4( - Buffer.from(privateKey.substring(2, 66), "hex"), - { - data: typedData, - } - ); + const signature = signTypedData_v4(Buffer.from(privateKey.substring(2, 66), 'hex'), { + data: typedData, + }); return fromRpcSig(signature); -}; \ No newline at end of file +}; diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index e2db2752..e893d6af 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -175,7 +175,8 @@ const initReserves = async ( lendingPoolAddressesProvider: LendingPoolAddressesProvider, lendingPool: LendingPool, lendingPoolConfigurator: LendingPoolConfigurator, - aavePool: AavePools + aavePool: AavePools, + incentivesController: tEthereumAddress ) => { if (aavePool !== AavePools.proto && aavePool !== AavePools.secondary) { console.log(`Invalid Aave pool ${aavePool}`); @@ -230,6 +231,7 @@ const initReserves = async ( `stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, tokenAddress, lendingPool.address, + incentivesController, ]); const variableDebtToken = await deployVariableDebtToken([ @@ -237,6 +239,7 @@ const initReserves = async ( `variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, tokenAddress, lendingPool.address, + incentivesController, ]); const aToken = await deployGenericAToken([ @@ -244,6 +247,7 @@ const initReserves = async ( tokenAddress, `Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, `a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, + incentivesController, ]); if (process.env.POOL === AavePools.secondary) { @@ -481,7 +485,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { addressesProvider, lendingPoolProxy, lendingPoolConfiguratorProxy, - AavePools.proto + AavePools.proto, + ZERO_ADDRESS ); await enableReservesToBorrow( reservesParams, From 1a7933762fc7280f9d4653021a632292136de251 Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 17:13:29 +0300 Subject: [PATCH 3/8] fix Upgradeability tests setup --- test/upgradeability.spec.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/upgradeability.spec.ts b/test/upgradeability.spec.ts index b2f50179..6139f3a4 100644 --- a/test/upgradeability.spec.ts +++ b/test/upgradeability.spec.ts @@ -10,6 +10,7 @@ import { import {MockAToken} from '../types/MockAToken'; import {MockStableDebtToken} from '../types/MockStableDebtToken'; import {MockVariableDebtToken} from '../types/MockVariableDebtToken'; +import {ZERO_ADDRESS} from '../helpers/constants'; makeSuite('Upgradeability', (testEnv: TestEnv) => { const {CALLER_NOT_LENDING_POOL_MANAGER} = ProtocolErrors; @@ -24,16 +25,29 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => { dai.address, 'Aave Interest bearing DAI updated', 'aDAI', + ZERO_ADDRESS, ]); const stableDebtTokenInstance = await deployContract( eContractid.MockStableDebtToken, - [pool.address, dai.address, 'Aave stable debt bearing DAI updated', 'stableDebtDAI'] + [ + pool.address, + dai.address, + 'Aave stable debt bearing DAI updated', + 'stableDebtDAI', + ZERO_ADDRESS, + ] ); const variableDebtTokenInstance = await deployContract( eContractid.MockVariableDebtToken, - [pool.address, dai.address, 'Aave variable debt bearing DAI updated', 'variableDebtDAI'] + [ + pool.address, + dai.address, + 'Aave variable debt bearing DAI updated', + 'variableDebtDAI', + ZERO_ADDRESS, + ] ); newATokenAddress = aTokenInstance.address; From 3340bb14fb61055f95a921000abdef0e76f68a7b Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 17:40:40 +0300 Subject: [PATCH 4/8] typo 0x0 -> 0 --- contracts/tokenization/ERC20.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/tokenization/ERC20.sol b/contracts/tokenization/ERC20.sol index 91194087..24257c3e 100644 --- a/contracts/tokenization/ERC20.sol +++ b/contracts/tokenization/ERC20.sol @@ -177,7 +177,7 @@ contract ERC20 is Context, IERC20, IERC20Detailed { uint256 oldRecipientBalance = _balances[recipient]; _balances[recipient] = _balances[recipient].add(amount); - if (address(_incentivesController) != address(0x0)) { + if (address(_incentivesController) != address(0)) { uint256 totalSupply = _totalSupply; _incentivesController.handleAction(sender, totalSupply, oldSenderBalance); _incentivesController.handleAction(recipient, totalSupply, oldRecipientBalance); @@ -196,7 +196,7 @@ contract ERC20 is Context, IERC20, IERC20Detailed { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.add(amount); - if (address(_incentivesController) != address(0x0)) { + if (address(_incentivesController) != address(0)) { _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); } @@ -214,7 +214,7 @@ contract ERC20 is Context, IERC20, IERC20Detailed { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance'); - if (address(_incentivesController) != address(0x0)) { + if (address(_incentivesController) != address(0)) { _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); } From 6af1e0923f5fc7fa2db0d11c1cdaaefb2cf3a7dc Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 17:49:53 +0300 Subject: [PATCH 5/8] fix _incentivesController call in _transfer --- contracts/tokenization/ERC20.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/tokenization/ERC20.sol b/contracts/tokenization/ERC20.sol index 24257c3e..d7d33ab9 100644 --- a/contracts/tokenization/ERC20.sol +++ b/contracts/tokenization/ERC20.sol @@ -180,7 +180,9 @@ contract ERC20 is Context, IERC20, IERC20Detailed { if (address(_incentivesController) != address(0)) { uint256 totalSupply = _totalSupply; _incentivesController.handleAction(sender, totalSupply, oldSenderBalance); - _incentivesController.handleAction(recipient, totalSupply, oldRecipientBalance); + if (sender != recipient) { + _incentivesController.handleAction(recipient, totalSupply, oldRecipientBalance); + } } emit Transfer(sender, recipient, amount); } From fba2f03c03ef7626dbb67968ed2b720753566746 Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 18:08:28 +0300 Subject: [PATCH 6/8] rename ERC20 to IncentivizedERC20 --- contracts/tokenization/AToken.sol | 28 ++++++++++--------- .../{ERC20.sol => IncentivizedERC20.sol} | 2 +- contracts/tokenization/base/DebtTokenBase.sol | 6 ++-- 3 files changed, 19 insertions(+), 17 deletions(-) rename contracts/tokenization/{ERC20.sol => IncentivizedERC20.sol} (99%) diff --git a/contracts/tokenization/AToken.sol b/contracts/tokenization/AToken.sol index 3c248fdb..b829350c 100644 --- a/contracts/tokenization/AToken.sol +++ b/contracts/tokenization/AToken.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.6.8; -import {ERC20} from './ERC20.sol'; +import {IncentivizedERC20} from './IncentivizedERC20.sol'; import {LendingPool} from '../lendingpool/LendingPool.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; @@ -18,9 +18,9 @@ import {SafeERC20} from '../misc/SafeERC20.sol'; * @dev Implementation of the interest bearing token for the DLP protocol. * @author Aave */ -contract AToken is VersionedInitializable, ERC20, IAToken { +contract AToken is VersionedInitializable, IncentivizedERC20, IAToken { using WadRayMath for uint256; - using SafeERC20 for ERC20; + using SafeERC20 for IncentivizedERC20; uint256 public constant UINT_MAX_VALUE = uint256(-1); address public immutable UNDERLYING_ASSET_ADDRESS; @@ -47,7 +47,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken { string memory tokenName, string memory tokenSymbol, address incentivesController - ) public ERC20(tokenName, tokenSymbol, 18, incentivesController) { + ) public IncentivizedERC20(tokenName, tokenSymbol, 18, incentivesController) { POOL = pool; UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress; } @@ -102,8 +102,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken { _burn(user, scaledAmount); //transfers the underlying to the target - ERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount); - + IncentivizedERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount); emit Burn(msg.sender, receiverOfUnderlying, amount, index); } @@ -144,11 +143,16 @@ contract AToken is VersionedInitializable, ERC20, IAToken { /** * @dev calculates the balance of the user, which is the - * principal balance + interest generated by the principal balance + * principal balance + interest generated by the principal balance * @param user the user for which the balance is being calculated * @return the total balance of the user **/ - function balanceOf(address user) public override(ERC20, IERC20) view returns (uint256) { + function balanceOf(address user) + public + override(IncentivizedERC20, IERC20) + view + returns (uint256) + { return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); } @@ -183,16 +187,14 @@ contract AToken is VersionedInitializable, ERC20, IAToken { * does that too. * @return the current total supply **/ - function totalSupply() public override(ERC20, IERC20) view returns (uint256) { + function totalSupply() public override(IncentivizedERC20, IERC20) view returns (uint256) { uint256 currentSupplyScaled = super.totalSupply(); if (currentSupplyScaled == 0) { return 0; } - return - currentSupplyScaled - .rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); + return currentSupplyScaled.rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)); } /** @@ -218,7 +220,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken { onlyLendingPool returns (uint256) { - ERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount); + IncentivizedERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount); return amount; } diff --git a/contracts/tokenization/ERC20.sol b/contracts/tokenization/IncentivizedERC20.sol similarity index 99% rename from contracts/tokenization/ERC20.sol rename to contracts/tokenization/IncentivizedERC20.sol index d7d33ab9..0d3aa311 100644 --- a/contracts/tokenization/ERC20.sol +++ b/contracts/tokenization/IncentivizedERC20.sol @@ -12,7 +12,7 @@ import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController * @notice Basic ERC20 implementation * @author Aave **/ -contract ERC20 is Context, IERC20, IERC20Detailed { +contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { using SafeMath for uint256; IAaveIncentivesController internal immutable _incentivesController; diff --git a/contracts/tokenization/base/DebtTokenBase.sol b/contracts/tokenization/base/DebtTokenBase.sol index f09e92d4..ceb51688 100644 --- a/contracts/tokenization/base/DebtTokenBase.sol +++ b/contracts/tokenization/base/DebtTokenBase.sol @@ -8,7 +8,7 @@ import {ILendingPool} from '../../interfaces/ILendingPool.sol'; import { VersionedInitializable } from '../../libraries/openzeppelin-upgradeability/VersionedInitializable.sol'; -import {ERC20} from '../ERC20.sol'; +import {IncentivizedERC20} from '../IncentivizedERC20.sol'; import {Errors} from '../../libraries/helpers/Errors.sol'; /** @@ -17,7 +17,7 @@ import {Errors} from '../../libraries/helpers/Errors.sol'; * @author Aave */ -abstract contract DebtTokenBase is ERC20, VersionedInitializable { +abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable { address internal immutable UNDERLYING_ASSET; ILendingPool internal immutable POOL; mapping(address => uint256) internal _usersData; @@ -40,7 +40,7 @@ abstract contract DebtTokenBase is ERC20, VersionedInitializable { string memory name, string memory symbol, address incentivesController - ) public ERC20(name, symbol, 18, incentivesController) { + ) public IncentivizedERC20(name, symbol, 18, incentivesController) { POOL = ILendingPool(pool); UNDERLYING_ASSET = underlyingAssetAddress; } From ee6d01743932604579f6758993f118103fce537d Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 18:11:43 +0300 Subject: [PATCH 7/8] update package-lock --- package-lock.json | 156 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 149 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b5eff61..80de030a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -801,6 +801,21 @@ "readdirp": "~3.4.0" } }, + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, "readdirp": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", @@ -862,6 +877,21 @@ "util.promisify": "^1.0.0" }, "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3970,6 +4000,21 @@ "sync-request": "^6.0.0" }, "dependencies": { + "ethereumjs-util": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", + "integrity": "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^2.0.0", + "rlp": "^2.2.3", + "secp256k1": "^3.0.1" + } + }, "ethers": { "version": "4.0.47", "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.47.tgz", @@ -4239,6 +4284,23 @@ "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } } }, "ethereumjs-account": { @@ -4250,6 +4312,23 @@ "ethereumjs-util": "^6.0.0", "rlp": "^2.2.1", "safe-buffer": "^5.1.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } } }, "ethereumjs-block": { @@ -4368,6 +4447,23 @@ "lru-cache": "^5.1.1", "rlp": "^2.2.2", "semaphore": "^1.1.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } } }, "ethereumjs-common": { @@ -4384,21 +4480,67 @@ "requires": { "ethereumjs-common": "^1.5.0", "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } } }, "ethereumjs-util": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", - "integrity": "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.2.tgz", + "integrity": "sha512-ATAP02eJLpAlWGfiKQddNrRfZpwXiTFhRN2EM/yLXMCdBW/xjKYblNKcx8GLzzrjXg0ymotck+lam1nuV90arQ==", "dev": true, "requires": { "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", + "bn.js": "^5.1.2", "create-hash": "^1.1.2", "ethjs-util": "0.1.6", - "keccak": "^2.0.0", - "rlp": "^2.2.3", - "secp256k1": "^3.0.1" + "keccak": "^3.0.0", + "rlp": "^2.2.4", + "secp256k1": "^4.0.1" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "dev": true, + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "dev": true, + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + } } }, "ethers": { From 5b7b4c517f9b55841b8e5343030e0bdbbf826b8c Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 15 Sep 2020 18:25:34 +0300 Subject: [PATCH 8/8] fix ci:test env --- buidler.config.ts | 4 ++-- helpers/buidler-constants.ts | 3 +++ helpers/constants.ts | 36 +++++++++++++++--------------------- test/atoken-permit.spec.ts | 2 +- 4 files changed, 21 insertions(+), 24 deletions(-) create mode 100644 helpers/buidler-constants.ts diff --git a/buidler.config.ts b/buidler.config.ts index dd736359..03f42645 100644 --- a/buidler.config.ts +++ b/buidler.config.ts @@ -1,8 +1,8 @@ -import {usePlugin, BuidlerConfig} from '@nomiclabs/buidler/config'; +import {usePlugin} from '@nomiclabs/buidler/config'; // @ts-ignore import {accounts} from './test-wallets.js'; import {eEthereumNetwork} from './helpers/types'; -import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/constants'; +import {BUIDLEREVM_CHAINID, COVERAGE_CHAINID} from './helpers/buidler-constants'; usePlugin('@nomiclabs/buidler-ethers'); usePlugin('buidler-typechain'); diff --git a/helpers/buidler-constants.ts b/helpers/buidler-constants.ts new file mode 100644 index 00000000..5eb044c3 --- /dev/null +++ b/helpers/buidler-constants.ts @@ -0,0 +1,3 @@ +export const TEST_SNAPSHOT_ID = '0x1'; +export const BUIDLEREVM_CHAINID = 31337; +export const COVERAGE_CHAINID = 1337; diff --git a/helpers/constants.ts b/helpers/constants.ts index 54a10de5..457a7f1d 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -1,22 +1,17 @@ import { - iAssetBase, - iAavePoolAssets, - IMarketRates, - iAssetAggregatorBase, AavePools, + eEthereumNetwork, + iAavePoolAssets, + iAssetAggregatorBase, + iAssetBase, + iBasicDistributionParams, + IMarketRates, iMultiPoolsAssets, IReserveParams, tEthereumAddress, - iBasicDistributionParams, - eEthereumNetwork, } from './types'; import BigNumber from 'bignumber.js'; -import {getParamPerPool, getParamPerNetwork} from './contracts-helpers'; - -export const TEST_SNAPSHOT_ID = '0x1'; - -export const BUIDLEREVM_CHAINID = 31337; -export const COVERAGE_CHAINID = 1337; +import {getParamPerNetwork, getParamPerPool} from './contracts-helpers'; // ---------------- // MATH @@ -536,17 +531,16 @@ export const getFeeDistributionParamsCommon = ( }; }; -export const getATokenDomainSeparatorPerNetwork = ( - network: eEthereumNetwork -): tEthereumAddress => +export const getATokenDomainSeparatorPerNetwork = (network: eEthereumNetwork): tEthereumAddress => getParamPerNetwork( { - [eEthereumNetwork.coverage]: "0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820", + [eEthereumNetwork.coverage]: + '0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820', [eEthereumNetwork.buidlerevm]: - "0x76cbbf8aa4b11a7c207dd79ccf8c394f59475301598c9a083f8258b4fafcfa86", - [eEthereumNetwork.kovan]: "", - [eEthereumNetwork.ropsten]: "", - [eEthereumNetwork.main]: "", + '0x76cbbf8aa4b11a7c207dd79ccf8c394f59475301598c9a083f8258b4fafcfa86', + [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '', }, network - ); \ No newline at end of file + ); diff --git a/test/atoken-permit.spec.ts b/test/atoken-permit.spec.ts index ef5a39e0..397eddb1 100644 --- a/test/atoken-permit.spec.ts +++ b/test/atoken-permit.spec.ts @@ -2,7 +2,6 @@ import { MAX_UINT_AMOUNT, ZERO_ADDRESS, getATokenDomainSeparatorPerNetwork, - BUIDLEREVM_CHAINID, } from '../helpers/constants'; import {buildPermitParams, getSignatureFromTypedData} from '../helpers/contracts-helpers'; import {expect} from 'chai'; @@ -11,6 +10,7 @@ import {eEthereumNetwork} from '../helpers/types'; import {makeSuite, TestEnv} from './helpers/make-suite'; import {BRE} from '../helpers/misc-utils'; import {waitForTx} from './__setup.spec'; +import {BUIDLEREVM_CHAINID} from '../helpers/buidler-constants'; const {parseEther} = ethers.utils;