From 39db9e4bc1891d017d271e3535897399c956a9ef Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 20 Apr 2021 11:07:30 +0200 Subject: [PATCH 1/8] feature: added dedicated payload contract for AIP 12 AMPL listing --- contracts/assetListing/AIP12AMPL.sol | 68 +++++++++++++++++++ ...etListingProposalGenericExecutor copy.sol} | 0 contracts/assetListing/interfaces/IAAMPL.sol | 6 ++ contracts/assetListing/interfaces/IERC20.sol | 2 + 4 files changed, 76 insertions(+) create mode 100644 contracts/assetListing/AIP12AMPL.sol rename contracts/assetListing/{AssetListingProposalGenericExecutor.sol => AssetListingProposalGenericExecutor copy.sol} (100%) create mode 100644 contracts/assetListing/interfaces/IAAMPL.sol diff --git a/contracts/assetListing/AIP12AMPL.sol b/contracts/assetListing/AIP12AMPL.sol new file mode 100644 index 0000000..7cdc85a --- /dev/null +++ b/contracts/assetListing/AIP12AMPL.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.6.12; + +import {IERC20} from './interfaces/IERC20.sol'; +import {ILendingPoolConfiguratorV2} from './interfaces/ILendingPoolConfiguratorV2.sol'; +import {IOverlyingAsset} from './interfaces/IOverlyingAsset.sol'; +import {ILendingPoolAddressesProvider} from './interfaces/ILendingPoolAddressesProvider.sol'; +import {IAAMPL} from './interfaces/IAAMPL.sol'; +import {ILendingPool, DataTypes} from './interfaces/ILendingPool.sol'; +/** + * @title AssetListingProposalGenericExecutor + * @notice Proposal payload to be executed by the Aave Governance contract via DELEGATECALL + * @author Aave + **/ +contract AssetListingProposalGenericExecutor { + event ProposalExecuted(); + + ILendingPoolAddressesProvider public constant LENDING_POOL_ADDRESSES_PROVIDER = + ILendingPoolAddressesProvider(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); + + address public constant token = 0xD46bA6D942050d489DBd938a2C909A5d5039A161; + address public constant aToken = 0x938Eb0b3C4Bb93aF924ACbf9d3dBD444153F7Ba8; + address public constant stableDebtToken = 0x0e8f4fc4c261d454b13C74507Bce8C38AA990361; + address public constant variableDebtToken = 0x3A38bbc6438d2CE2a9e8F116F315a23433755947; + address public constant interestStrategy = 0x9A8CA7e1d64AFfF2664443B3803f280345F5336B; + uint256 public constant ltv = 0; + uint256 public constant liquidationThreshold = 0; + uint256 public constant liquidationBonus = 0; + uint256 public constant reserveFactor = 2000; + uint8 decimals = 9; + + /** + * @dev Payload execution function, called once a proposal passed in the Aave governance + */ + function execute() external { + ILendingPoolConfiguratorV2 LENDING_POOL_CONFIGURATOR_V2 = + ILendingPoolConfiguratorV2(LENDING_POOL_ADDRESSES_PROVIDER.getLendingPoolConfigurator()); + require( + token == IOverlyingAsset(aToken).UNDERLYING_ASSET_ADDRESS(), + 'ATOKEN: WRONG_UNDERLYING_TOKEN' + ); + require( + token == IOverlyingAsset(stableDebtToken).UNDERLYING_ASSET_ADDRESS(), + 'STABLE_DEBT: WRONG_UNDERLYING_TOKEN' + ); + require( + token == IOverlyingAsset(variableDebtToken).UNDERLYING_ASSET_ADDRESS(), + 'VARIABLE_DEBT: WRONG_UNDERLYING_TOKEN' + ); + LENDING_POOL_CONFIGURATOR_V2.initReserve( + aToken, + stableDebtToken, + variableDebtToken, + decimals, + interestStrategy + ); + LENDING_POOL_CONFIGURATOR_V2.enableBorrowingOnReserve(token, false); + LENDING_POOL_CONFIGURATOR_V2.setReserveFactor(token, reserveFactor); + + ILendingPool pool = ILendingPool(LENDING_POOL_ADDRESSES_PROVIDER.getLendingPool()); + + DataTypes.ReserveData memory reserve = pool.getReserveData(token); + + IAAMPL(reserve.aTokenAddress).setDebtTokens(reserve.stableDebtTokenAddress, reserve.variableDebtTokenAddress); + + emit ProposalExecuted(); + } +} diff --git a/contracts/assetListing/AssetListingProposalGenericExecutor.sol b/contracts/assetListing/AssetListingProposalGenericExecutor copy.sol similarity index 100% rename from contracts/assetListing/AssetListingProposalGenericExecutor.sol rename to contracts/assetListing/AssetListingProposalGenericExecutor copy.sol diff --git a/contracts/assetListing/interfaces/IAAMPL.sol b/contracts/assetListing/interfaces/IAAMPL.sol new file mode 100644 index 0000000..93553a6 --- /dev/null +++ b/contracts/assetListing/interfaces/IAAMPL.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +interface IAAMPL { + function setDebtTokens(address stableDebt, address variableDebt) external; +} diff --git a/contracts/assetListing/interfaces/IERC20.sol b/contracts/assetListing/interfaces/IERC20.sol index bc05d95..9cb452c 100644 --- a/contracts/assetListing/interfaces/IERC20.sol +++ b/contracts/assetListing/interfaces/IERC20.sol @@ -65,6 +65,8 @@ interface IERC20 { uint256 amount ) external returns (bool); + function decimals() external view returns (uint8); + /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). From 0f5794f1730f0adb84f7f3702598f8f76316c403 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 20 Apr 2021 11:12:56 +0200 Subject: [PATCH 2/8] fix: added abicoder v2 for proposal, dataType --- contracts/assetListing/AIP12AMPL.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/assetListing/AIP12AMPL.sol b/contracts/assetListing/AIP12AMPL.sol index 7cdc85a..b0edacc 100644 --- a/contracts/assetListing/AIP12AMPL.sol +++ b/contracts/assetListing/AIP12AMPL.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; import {IERC20} from './interfaces/IERC20.sol'; import {ILendingPoolConfiguratorV2} from './interfaces/ILendingPoolConfiguratorV2.sol'; From 2c34998fe394f1896256a0555651dbb8842e22d5 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 20 Apr 2021 14:31:22 +0200 Subject: [PATCH 3/8] fix: decimals as public const, name of contract AIP12, name of AssetListing --- contracts/assetListing/AIP12AMPL.sol | 4 ++-- ...cutor copy.sol => AssetListingProposalGenericExecutor.sol} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename contracts/assetListing/{AssetListingProposalGenericExecutor copy.sol => AssetListingProposalGenericExecutor.sol} (100%) diff --git a/contracts/assetListing/AIP12AMPL.sol b/contracts/assetListing/AIP12AMPL.sol index b0edacc..e75ce6d 100644 --- a/contracts/assetListing/AIP12AMPL.sol +++ b/contracts/assetListing/AIP12AMPL.sol @@ -13,7 +13,7 @@ import {ILendingPool, DataTypes} from './interfaces/ILendingPool.sol'; * @notice Proposal payload to be executed by the Aave Governance contract via DELEGATECALL * @author Aave **/ -contract AssetListingProposalGenericExecutor { +contract AIP12AMPL { event ProposalExecuted(); ILendingPoolAddressesProvider public constant LENDING_POOL_ADDRESSES_PROVIDER = @@ -28,7 +28,7 @@ contract AssetListingProposalGenericExecutor { uint256 public constant liquidationThreshold = 0; uint256 public constant liquidationBonus = 0; uint256 public constant reserveFactor = 2000; - uint8 decimals = 9; + uint8 public constant decimals = 9; /** * @dev Payload execution function, called once a proposal passed in the Aave governance diff --git a/contracts/assetListing/AssetListingProposalGenericExecutor copy.sol b/contracts/assetListing/AssetListingProposalGenericExecutor.sol similarity index 100% rename from contracts/assetListing/AssetListingProposalGenericExecutor copy.sol rename to contracts/assetListing/AssetListingProposalGenericExecutor.sol From 549972dd0b2cf8ec75adc9f6e6994cb29c1a727e Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 20 Apr 2021 14:32:28 +0200 Subject: [PATCH 4/8] test: added test for aip 12 payload, adding AMPL --- package.json | 1 + test/test-listing-ampl.spec.ts | 269 +++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 test/test-listing-ampl.spec.ts diff --git a/package.json b/package.json index 374567c..c14f204 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "test:crv": "MAINNET_FORK=true FORKING_BLOCK=11538355 hardhat test ./test/test-listing-crv.spec.ts", "test:bal": "MAINNET_FORK=true FORKING_BLOCK=11743368 hardhat test ./test/test-listing-bal.spec.ts", "test:xsushi": "MAINNET_FORK=true FORKING_BLOCK=11829845 hardhat test ./test/test-listing-xsushi.spec.ts", + "test:ampl": "MAINNET_FORK=true FORKING_BLOCK=12245642 hardhat test ./test/test-listing-ampl.spec.ts", "run-env": "npm i && tail -f /dev/null", "propose-new-asset:kovan": "hardhat create:proposal-new-asset --network kovan", "propose-new-asset:main": "hardhat create:proposal-new-asset --network main" diff --git a/test/test-listing-ampl.spec.ts b/test/test-listing-ampl.spec.ts new file mode 100644 index 0000000..23c9d8c --- /dev/null +++ b/test/test-listing-ampl.spec.ts @@ -0,0 +1,269 @@ +import path from 'path'; +import { expect } from 'chai'; +import { config } from 'dotenv'; + +import rawBRE, { ethers } from 'hardhat'; + +import { BigNumber } from 'ethers'; +import { parseEther } from 'ethers/lib/utils'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/dist/src/signer-with-address'; +import { JsonRpcSigner } from '@ethersproject/providers'; +import { + evmSnapshot, + increaseTime, + evmRevert, + latestBlock, + advanceBlockTo, + impersonateAccountsHardhat, + MAX_UINT_AMOUNT, +} from './utils/utils'; +import { parsePoolData } from './utils/listing'; +import { IAaveGovernanceV2 } from '../types/IAaveGovernanceV2'; +import { IAaveOracle } from '../types/IAaveOracle'; +import { ILendingPool } from '../types/ILendingPool'; +import { SelfdestructTransferFactory } from '../types/SelfdestructTransferFactory' +import { IERC20 } from '../types/IERC20'; + +const { + TOKEN, + ATOKEN, + STABLE_DEBT_TOKEN, + VARIABLE_DEBT_TOKEN, + INTEREST_STRATEGY, + LTV, + LIQUIDATION_THRESHOLD, + LIQUIDATION_BONUS, + RESERVE_FACTOR, + DECIMALS, + IPFS_HASH, + AAVE_GOVERNANCE_V2 = '0xEC568fffba86c094cf06b22134B23074DFE2252c', // mainnet + AAVE_SHORT_EXECUTOR = '0xee56e2b3d491590b5b31738cc34d5232f378a8d5', // mainnet +} = process.env; + +if ( + !TOKEN || + !ATOKEN || + !STABLE_DEBT_TOKEN || + !VARIABLE_DEBT_TOKEN || + !INTEREST_STRATEGY || + !LTV || + !LIQUIDATION_BONUS || + !LIQUIDATION_THRESHOLD || + !DECIMALS || + !IPFS_HASH || + !AAVE_GOVERNANCE_V2 || + !AAVE_SHORT_EXECUTOR || + !RESERVE_FACTOR +) { + throw new Error('You have not set correctly the .env file, make sure to read the README.md'); +} + +let k = 0; + +const log = ( ) => { + console.log(k++); + +} + +const AAVE_LENDING_POOL = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9'; +const VOTING_DURATION = 19200; + +const AAVE_WHALE = '0x25f2226b597e8f9514b3f68f00f494cf4f286491'; +const AAVE_TOKEN = '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9'; + +const AMPL_HOLDER = '0xbdb30Cf89eFdd8C7410d9b3d0De04bC41B962770'; +const AAVE_ORACLE_OWNER = '0xb9062896ec3a615a4e4444df183f0531a77218ae'; +const AAVE_ORACLE = '0xa50ba011c48153de246e5192c8f9258a2ba79ca9'; + +const DAI_TOKEN = '0x6b175474e89094c44da98b954eedeac495271d0f'; +const DAI_HOLDER = '0x72aabd13090af25dbb804f84de6280c697ed1150'; + +const ERRORS = { + NO_BORROW: '7', + NO_COLLATERAL_BALANCE: '9', + NO_STABLE_BORROW: '12', +}; + +describe('Deploy AMPL assets with different params', () => { + let whale: JsonRpcSigner; + let amplHolder: JsonRpcSigner; + let daiHolder: JsonRpcSigner; + let proposer: SignerWithAddress; + let gov: IAaveGovernanceV2; + let pool: ILendingPool; + let oracle: IAaveOracle; + let aave: IERC20; + let ampl: IERC20; + let dai: IERC20; + let aAmpl: IERC20; + let stableDebt: IERC20; + let variableDebt: IERC20; + let proposal: BigNumber; + let snapshotId: string; + let decimalMultiplier: BigNumber; + before(async () => { + [proposer] = await rawBRE.ethers.getSigners(); + // send ether to the AAVE_WHALE, which is a non payable contract. Via selfdestruct + await rawBRE.deployments.deploy('SelfdestructTransfer', { from: proposer.address }); + let selfDestructContract = await new SelfdestructTransferFactory(proposer).deploy(); + await ( + await selfDestructContract.destroyAndTransfer(AAVE_WHALE, { + value: ethers.utils.parseEther('1'), + }) + ).wait(); + selfDestructContract = await new SelfdestructTransferFactory(proposer).deploy(); + await ( + await selfDestructContract.destroyAndTransfer(AMPL_HOLDER, { + value: ethers.utils.parseEther('1'), + }) + ).wait(); + await impersonateAccountsHardhat([AAVE_WHALE, AMPL_HOLDER, AAVE_ORACLE_OWNER, DAI_HOLDER]); + + // impersonating holders + + whale = ethers.provider.getSigner(AAVE_WHALE); + amplHolder = ethers.provider.getSigner(AMPL_HOLDER); + daiHolder = ethers.provider.getSigner(DAI_HOLDER); + //getting main entry point contracts + gov = (await ethers.getContractAt( + 'IAaveGovernanceV2', + AAVE_GOVERNANCE_V2, + proposer + )) as IAaveGovernanceV2; + pool = (await ethers.getContractAt( + 'ILendingPool', + AAVE_LENDING_POOL, + proposer + )) as ILendingPool; + + // getting tokens used for tests + aave = (await ethers.getContractAt('IERC20', AAVE_TOKEN, whale)) as IERC20; + dai = (await ethers.getContractAt('IERC20', DAI_TOKEN, daiHolder)) as IERC20; + ampl = (await ethers.getContractAt('IERC20', TOKEN, amplHolder)) as IERC20; + decimalMultiplier = BigNumber.from('10').pow(await ampl.decimals()); + // give ampl to whale + + await ( + await aave.transfer( + proposer.address, + (await aave.balanceOf(AAVE_WHALE)).sub(parseEther('10000')) + ) + ).wait(); + + // giving just a bit of Dai to Crv holder to pay for interest later + await (await dai.transfer(AMPL_HOLDER, parseEther('10'))).wait(); + console.log(((await ampl.balanceOf(AMPL_HOLDER)).toString())) + console.log(((await ampl.decimals()).toString())) + await ( + await ampl.transfer( + proposer.address, + (await ampl.balanceOf(AMPL_HOLDER)).sub((parseEther('1000').div(decimalMultiplier))) + ) + ).wait(); + + + // deploying the payload + await rawBRE.ethers.provider.send('evm_mine', [0]); + await rawBRE.deployments.deploy('AIP12AMPL', { + from: proposer.address, + gasLimit: 4000000, + gasPrice: BigNumber.from('75000000000'), + args: [], + }); + + + proposal = await gov.getProposalsCount(); + await rawBRE.run('list:ampl'); + + // voting, queuing proposals + await rawBRE.ethers.provider.send('evm_mine', [0]); + + await (await gov.submitVote(proposal, true)).wait(); + await advanceBlockTo((await latestBlock()) + VOTING_DURATION + 1); + log(); + await (await gov.queue(proposal)).wait(); + let proposalState = await gov.getProposalState(proposal); + expect(proposalState).to.be.equal(5); + await increaseTime(86400 + 10); + snapshotId = await evmSnapshot(); + }); + it('Should list correctly an asset: borrow on, collateral off, stable borrow off', async () => { + await (await gov.execute(proposal)).wait(); + const proposalState = await gov.getProposalState(proposal); + expect(proposalState).to.be.equal(7); + const { + configuration: { data }, + aTokenAddress, + stableDebtTokenAddress, + variableDebtTokenAddress, + } = await pool.getReserveData(TOKEN); + const poolData = parsePoolData(data); + expect(poolData).to.be.eql({ + reserveFactor: RESERVE_FACTOR, + reserved: '0', + stableRateEnabled: '0', + borrowingEnabled: '1', + reserveFrozen: '0', + reserveActive: '1', + decimals: DECIMALS, + liquidityBonus: '0', + LiquidityThreshold: '0', + LTV: '0', + }); + + // preparing for tests. + aAmpl = (await ethers.getContractAt('IERC20', aTokenAddress, proposer)) as IERC20; + stableDebt = (await ethers.getContractAt('IERC20', stableDebtTokenAddress, proposer)) as IERC20; + variableDebt = (await ethers.getContractAt( + 'IERC20', + variableDebtTokenAddress, + proposer + )) as IERC20; + log() + console.log('1') + await (await ampl.connect(amplHolder).approve(pool.address, parseEther('200000'))).wait(); + log() + await (await aave.connect(proposer).approve(pool.address, parseEther('200000'))).wait(); + + // AAVE deposit by proposer + await (await pool.deposit(aave.address, parseEther('100'), proposer.address, 0)).wait(); + log() + // AMPL deposit by ampl holder + const depositedAmount = parseEther('100').div(decimalMultiplier); + console.log(depositedAmount.toString()) + console.log((await ampl.balanceOf(AMPL_HOLDER)).toString()) + console.log((await ampl.allowance(AMPL_HOLDER, pool.address)).toString()) + await ( + await pool.connect(amplHolder).deposit(ampl.address, depositedAmount, AMPL_HOLDER, 0) + ).wait(); + console.log('eheh') + expect(await aAmpl.balanceOf(AMPL_HOLDER)).to.be.equal(depositedAmount); + log() + console.log('eheh') + + // AMPL holder not able to borrow DAI against AMPL + await expect( + pool.connect(amplHolder).borrow(dai.address, parseEther('1'), 2, 0, AMPL_HOLDER) + ).to.be.revertedWith(ERRORS.NO_COLLATERAL_BALANCE); + + // proposer able to borrow AMPL variable against AAVE + const borrowAmount = parseEther('10').div(decimalMultiplier); + await ( + await pool.connect(proposer).borrow(ampl.address, borrowAmount, 2, 0, proposer.address) + ).wait(); + expect(await variableDebt.balanceOf(proposer.address)).to.be.equal(borrowAmount); + log() + console.log('eheh') + + // proposer not able to borrow AMPL stable against AAVE + await expect( + pool.borrow(ampl.address, parseEther('5'), 1, 0, proposer.address) + ).to.be.revertedWith(ERRORS.NO_STABLE_BORROW); + increaseTime(40000); + + // proposer able to repay AMPL variable + await (await ampl.connect(proposer).approve(pool.address, parseEther('100000'))).wait(); + await (await pool.repay(ampl.address, MAX_UINT_AMOUNT, 2, proposer.address)).wait(); + expect(await variableDebt.balanceOf(proposer.address)).to.be.equal(parseEther('0')); + }); +}); From ecef95665c554fcf122504a474095f862c5f5cdc Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 20 Apr 2021 15:26:27 +0200 Subject: [PATCH 5/8] clean: removed logs --- test/test-listing-ampl.spec.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/test-listing-ampl.spec.ts b/test/test-listing-ampl.spec.ts index 23c9d8c..eebf260 100644 --- a/test/test-listing-ampl.spec.ts +++ b/test/test-listing-ampl.spec.ts @@ -61,7 +61,6 @@ if ( let k = 0; const log = ( ) => { - console.log(k++); } @@ -152,8 +151,6 @@ describe('Deploy AMPL assets with different params', () => { // giving just a bit of Dai to Crv holder to pay for interest later await (await dai.transfer(AMPL_HOLDER, parseEther('10'))).wait(); - console.log(((await ampl.balanceOf(AMPL_HOLDER)).toString())) - console.log(((await ampl.decimals()).toString())) await ( await ampl.transfer( proposer.address, @@ -220,7 +217,6 @@ describe('Deploy AMPL assets with different params', () => { proposer )) as IERC20; log() - console.log('1') await (await ampl.connect(amplHolder).approve(pool.address, parseEther('200000'))).wait(); log() await (await aave.connect(proposer).approve(pool.address, parseEther('200000'))).wait(); @@ -230,16 +226,11 @@ describe('Deploy AMPL assets with different params', () => { log() // AMPL deposit by ampl holder const depositedAmount = parseEther('100').div(decimalMultiplier); - console.log(depositedAmount.toString()) - console.log((await ampl.balanceOf(AMPL_HOLDER)).toString()) - console.log((await ampl.allowance(AMPL_HOLDER, pool.address)).toString()) await ( await pool.connect(amplHolder).deposit(ampl.address, depositedAmount, AMPL_HOLDER, 0) ).wait(); - console.log('eheh') expect(await aAmpl.balanceOf(AMPL_HOLDER)).to.be.equal(depositedAmount); log() - console.log('eheh') // AMPL holder not able to borrow DAI against AMPL await expect( @@ -253,7 +244,6 @@ describe('Deploy AMPL assets with different params', () => { ).wait(); expect(await variableDebt.balanceOf(proposer.address)).to.be.equal(borrowAmount); log() - console.log('eheh') // proposer not able to borrow AMPL stable against AAVE await expect( From 4067329917a970d1828b2de28e9388320323d5da Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Wed, 21 Apr 2021 09:42:54 +0200 Subject: [PATCH 6/8] feat: added tolerance to aAMPL balance after deposit --- test/test-listing-ampl.spec.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/test/test-listing-ampl.spec.ts b/test/test-listing-ampl.spec.ts index eebf260..cb8ea5e 100644 --- a/test/test-listing-ampl.spec.ts +++ b/test/test-listing-ampl.spec.ts @@ -58,12 +58,6 @@ if ( throw new Error('You have not set correctly the .env file, make sure to read the README.md'); } -let k = 0; - -const log = ( ) => { - -} - const AAVE_LENDING_POOL = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9'; const VOTING_DURATION = 19200; @@ -177,7 +171,6 @@ describe('Deploy AMPL assets with different params', () => { await (await gov.submitVote(proposal, true)).wait(); await advanceBlockTo((await latestBlock()) + VOTING_DURATION + 1); - log(); await (await gov.queue(proposal)).wait(); let proposalState = await gov.getProposalState(proposal); expect(proposalState).to.be.equal(5); @@ -216,21 +209,18 @@ describe('Deploy AMPL assets with different params', () => { variableDebtTokenAddress, proposer )) as IERC20; - log() await (await ampl.connect(amplHolder).approve(pool.address, parseEther('200000'))).wait(); - log() await (await aave.connect(proposer).approve(pool.address, parseEther('200000'))).wait(); // AAVE deposit by proposer await (await pool.deposit(aave.address, parseEther('100'), proposer.address, 0)).wait(); - log() // AMPL deposit by ampl holder const depositedAmount = parseEther('100').div(decimalMultiplier); await ( await pool.connect(amplHolder).deposit(ampl.address, depositedAmount, AMPL_HOLDER, 0) ).wait(); - expect(await aAmpl.balanceOf(AMPL_HOLDER)).to.be.equal(depositedAmount); - log() + expect(await aAmpl.balanceOf(AMPL_HOLDER)).to.gte(depositedAmount.sub(1)); + expect(await aAmpl.balanceOf(AMPL_HOLDER)).to.lte(depositedAmount.add(1)); // AMPL holder not able to borrow DAI against AMPL await expect( @@ -243,7 +233,6 @@ describe('Deploy AMPL assets with different params', () => { await pool.connect(proposer).borrow(ampl.address, borrowAmount, 2, 0, proposer.address) ).wait(); expect(await variableDebt.balanceOf(proposer.address)).to.be.equal(borrowAmount); - log() // proposer not able to borrow AMPL stable against AAVE await expect( From 30b9534072c9e7c7c25be755664e94a080c297d4 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Wed, 21 Apr 2021 10:07:28 +0200 Subject: [PATCH 7/8] feat: added ampl env --- .ampl.env | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .ampl.env diff --git a/.ampl.env b/.ampl.env new file mode 100644 index 0000000..c8972a8 --- /dev/null +++ b/.ampl.env @@ -0,0 +1,22 @@ +# in GWEI +# DEFAULT_GAS_PRICE= 50 +TOKEN=0xd46ba6d942050d489dbd938a2c909a5d5039a161 +ATOKEN=0x938Eb0b3C4Bb93aF924ACbf9d3dBD444153F7Ba8 +STABLE_DEBT_TOKEN=0x0e8f4fc4c261d454b13C74507Bce8C38AA990361 +VARIABLE_DEBT_TOKEN=0x3A38bbc6438d2CE2a9e8F116F315a23433755947 +INTEREST_STRATEGY=0x9A8CA7e1d64AFfF2664443B3803f280345F5336B +LTV=0 +LIQUIDATION_THRESHOLD=0 +LIQUIDATION_BONUS=0 +RESERVE_FACTOR=2000 +DECIMALS=9 +ENABLE_BORROW=true +ENABLE_STABLE_BORROW=false +ENABLE_AS_COLLATERAL=false +IPFS_HASH=QmX24WkPm4WLurTq4R24Neo1KMV3hs9KCg2EkhAYcQvV1e + +# By default executor and governance addresses set to mainnet addresses +# Uncomment the following for kovan +#AAVE_SHORT_EXECUTOR=0x2012b02574f32a96b9cfb8ba7fdfd589d5c70f50 +#AAVE_GOVERNANCE_V2=0xc2ebab3bac8f2f5028f5c7317027a41ebfca31d2 + From 727a3eb0c0331a0144e5f36c76b772aacc4cdf2e Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 10 May 2021 14:17:34 +0200 Subject: [PATCH 8/8] test: updated test for ampl --- .ampl.env | 2 +- contracts/assetListing/AIP12AMPL.sol | 4 +- contracts/assetListing/interfaces/IAAMPL.sol | 2 +- hardhat.config.ts | 1 + package.json | 2 +- tasks/list-ampl.ts | 51 ++++++++++++++++++++ test/test-listing-ampl.spec.ts | 2 +- 7 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 tasks/list-ampl.ts diff --git a/.ampl.env b/.ampl.env index c8972a8..a447b25 100644 --- a/.ampl.env +++ b/.ampl.env @@ -1,7 +1,7 @@ # in GWEI # DEFAULT_GAS_PRICE= 50 TOKEN=0xd46ba6d942050d489dbd938a2c909a5d5039a161 -ATOKEN=0x938Eb0b3C4Bb93aF924ACbf9d3dBD444153F7Ba8 +ATOKEN=0x6fBC3BE5ee5273598d1491D41bB45F6d05a7541A STABLE_DEBT_TOKEN=0x0e8f4fc4c261d454b13C74507Bce8C38AA990361 VARIABLE_DEBT_TOKEN=0x3A38bbc6438d2CE2a9e8F116F315a23433755947 INTEREST_STRATEGY=0x9A8CA7e1d64AFfF2664443B3803f280345F5336B diff --git a/contracts/assetListing/AIP12AMPL.sol b/contracts/assetListing/AIP12AMPL.sol index e75ce6d..e37c14b 100644 --- a/contracts/assetListing/AIP12AMPL.sol +++ b/contracts/assetListing/AIP12AMPL.sol @@ -20,7 +20,7 @@ contract AIP12AMPL { ILendingPoolAddressesProvider(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); address public constant token = 0xD46bA6D942050d489DBd938a2C909A5d5039A161; - address public constant aToken = 0x938Eb0b3C4Bb93aF924ACbf9d3dBD444153F7Ba8; + address public constant aToken = 0x6fBC3BE5ee5273598d1491D41bB45F6d05a7541A; address public constant stableDebtToken = 0x0e8f4fc4c261d454b13C74507Bce8C38AA990361; address public constant variableDebtToken = 0x3A38bbc6438d2CE2a9e8F116F315a23433755947; address public constant interestStrategy = 0x9A8CA7e1d64AFfF2664443B3803f280345F5336B; @@ -62,7 +62,7 @@ contract AIP12AMPL { DataTypes.ReserveData memory reserve = pool.getReserveData(token); - IAAMPL(reserve.aTokenAddress).setDebtTokens(reserve.stableDebtTokenAddress, reserve.variableDebtTokenAddress); + IAAMPL(reserve.aTokenAddress).initializeDebtTokens(); emit ProposalExecuted(); } diff --git a/contracts/assetListing/interfaces/IAAMPL.sol b/contracts/assetListing/interfaces/IAAMPL.sol index 93553a6..396d912 100644 --- a/contracts/assetListing/interfaces/IAAMPL.sol +++ b/contracts/assetListing/interfaces/IAAMPL.sol @@ -2,5 +2,5 @@ pragma solidity 0.6.12; interface IAAMPL { - function setDebtTokens(address stableDebt, address variableDebt) external; + function initializeDebtTokens() external; } diff --git a/hardhat.config.ts b/hardhat.config.ts index dbd9840..d1e0cbc 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -11,6 +11,7 @@ import '@nomiclabs/hardhat-waffle'; if (process.env.SKIP_LOAD !== 'true') { // eslint-disable-next-line global-require require('./tasks/list-new-asset.ts'); + require('./tasks/list-ampl.ts'); } export const BUIDLEREVM_CHAIN_ID = 31337; diff --git a/package.json b/package.json index c14f204..699e943 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "test:crv": "MAINNET_FORK=true FORKING_BLOCK=11538355 hardhat test ./test/test-listing-crv.spec.ts", "test:bal": "MAINNET_FORK=true FORKING_BLOCK=11743368 hardhat test ./test/test-listing-bal.spec.ts", "test:xsushi": "MAINNET_FORK=true FORKING_BLOCK=11829845 hardhat test ./test/test-listing-xsushi.spec.ts", - "test:ampl": "MAINNET_FORK=true FORKING_BLOCK=12245642 hardhat test ./test/test-listing-ampl.spec.ts", + "test:ampl": "MAINNET_FORK=true FORKING_BLOCK=12406480 hardhat test ./test/test-listing-ampl.spec.ts", "run-env": "npm i && tail -f /dev/null", "propose-new-asset:kovan": "hardhat create:proposal-new-asset --network kovan", "propose-new-asset:main": "hardhat create:proposal-new-asset --network main" diff --git a/tasks/list-ampl.ts b/tasks/list-ampl.ts new file mode 100644 index 0000000..9d81ca7 --- /dev/null +++ b/tasks/list-ampl.ts @@ -0,0 +1,51 @@ +import { task } from 'hardhat/config'; +import '@nomiclabs/hardhat-ethers'; +import { getContractAt } from '@nomiclabs/hardhat-ethers/dist/src/helpers'; +import { config } from 'dotenv'; +import { IAaveGovernanceV2 } from '../types/IAaveGovernanceV2'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const bs58 = require('bs58'); +const AAVE_GOVERNANCE_V2 = '0xEC568fffba86c094cf06b22134B23074DFE2252c'; // mainnet +const AAVE_SHORT_EXECUTOR = '0xee56e2b3d491590b5b31738cc34d5232f378a8d5'; // mainnet + +config(); + +task('list:ampl', 'Create some proposals and votes') + // eslint-disable-next-line no-empty-pattern + .setAction(async ({}, _DRE: HardhatRuntimeEnvironment) => { + const { + IPFS_HASH, + } = process.env; + if ( + !IPFS_HASH + ) { + throw new Error('please set `IPFS_HASH` as environment variable'); + } + const proposer = (await _DRE.ethers.getSigners())[0]; + const genericPayloadAddress = ( + await _DRE.deployments.get('AIP12AMPL') + ).address; + const executeCallData = new _DRE.ethers.utils.Interface(['function execute()']).encodeFunctionData('execute'); + const gov = (await getContractAt( + _DRE, + 'IAaveGovernanceV2', + AAVE_GOVERNANCE_V2 || '' + )) as IAaveGovernanceV2; + const ipfsEncoded = `0x${bs58.decode(IPFS_HASH).slice(2).toString('hex')}`; + + await ( + await gov + .connect(proposer) + .create( + AAVE_SHORT_EXECUTOR, + [genericPayloadAddress], + ['0'], + [''], + [executeCallData], + [true], + ipfsEncoded + ) + ).wait(); + console.log('Your Proposal has been submitted'); + }); diff --git a/test/test-listing-ampl.spec.ts b/test/test-listing-ampl.spec.ts index cb8ea5e..e53caba 100644 --- a/test/test-listing-ampl.spec.ts +++ b/test/test-listing-ampl.spec.ts @@ -236,7 +236,7 @@ describe('Deploy AMPL assets with different params', () => { // proposer not able to borrow AMPL stable against AAVE await expect( - pool.borrow(ampl.address, parseEther('5'), 1, 0, proposer.address) + pool.borrow(ampl.address, borrowAmount, 1, 0, proposer.address) ).to.be.revertedWith(ERRORS.NO_STABLE_BORROW); increaseTime(40000);