diff --git a/hardhat.config.ts b/hardhat.config.ts index a10e0f9..a735d9f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -115,10 +115,11 @@ const config: HardhatUserConfig = { mnemonic: mnemonic.mainnet, initialIndex: 0, count: 10, - } + }, + chainId: 1, }, mumbai: { - url: `https://polygon-mumbai.g.alchemy.io/v2/${process.env.ALCHEMY_MUMBAI_API_KEY}`, + url: `https://polygon-mumbai.g.alchemy.com/v2/${process.env.ALCHEMY_MUMBAI_API_KEY}`, gasPrice: 10e9, accounts: { mnemonic: mnemonic.testnet, diff --git a/package.json b/package.json index 4275082..78c48fc 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@types/node": ">=12.0.0", "chai": "^4.2.0", "erc20permit": "0.0.4", - "ethers": "^6.6.2", + "ethers": "6.6.4", "hardhat": "^2.14.0", "hardhat-deploy": "^0.11.34", "hardhat-deploy-ethers": "^0.4.1", @@ -53,8 +53,5 @@ "@openzeppelin/contracts": "^3.2.0", "@openzeppelin/contracts-upgradeable": "^3.3.0", "dotenv": "^16.3.1" - }, - "scripts": { - "test": "yarn hardhat test --network hardhat" } } diff --git a/scripts/execute_for_account.ts b/scripts/execute_for_account.ts new file mode 100644 index 0000000..08304a1 --- /dev/null +++ b/scripts/execute_for_account.ts @@ -0,0 +1,47 @@ +import { ethers, getNamedAccounts } from "hardhat"; + +async function main() { + const { deployer } = await getNamedAccounts(); + const receiver = '0x03828b7129d49313b2cdc966e50369b75ec79a48'; + const chargedParticlesAddress = '0xaB1a1410EA40930755C1330Cc0fB3367897C8c41'; + + console.log('deployer = ', deployer); + + // const chargedParticles: ChargedParticles = await ethers.getContractAt('ChargedParticles', '0x51f845af34c60499a1056FCDf47BcBC681A0fA39'); + const manager = await ethers.getContractAt('AaveWalletManager', '0x54b32b288d7904D5d98Be1910975a80e45DA5e8d'); + console.log(`manager address = `, manager.target); + + const setControllerTxBefore = await manager.setController(deployer).then(tx => tx.wait()); + console.log(`set ctrl tx = `, setControllerTxBefore?.hash); + + const dischargeInterface = (recipient: string, amount: BigInt) => { + const ABI = ["function transfer(address recipient, uint256 amount)"]; + const iface = new ethers.Interface(ABI); + const cdata = iface.encodeFunctionData("transfer", [recipient, amount]); + + return cdata; + }; + + const amountDeposit = 164000000000n; + console.log('amountDeposit = ' + amountDeposit.toString()); + + const dischargeCallData = dischargeInterface(receiver, amountDeposit); + console.log(`dischargeCallData = `, dischargeCallData); + + const executeTx = await manager.executeForAccount( + '0x63174FA9680C674a5580f7d747832B2a2133Ad8f', //ProtonC + 103, //Token ID + '0x1E6bb68Acec8fefBD87D192bE09bb274170a0548', //Asset + 0, + dischargeCallData + ).then(tx => tx.wait()); + console.log(`execute tx = `, executeTx?.hash); + + const setControllerTxAfter = await manager.setController(chargedParticlesAddress).then(tx => tx.wait()); + console.log(`reset ctrl tx = `, setControllerTxAfter?.hash) +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/scripts/remove_ampl_trap.ts b/scripts/remove_ampl_trap.ts new file mode 100644 index 0000000..f44f61a --- /dev/null +++ b/scripts/remove_ampl_trap.ts @@ -0,0 +1,36 @@ +import { ethers, getNamedAccounts } from "hardhat"; + +async function main() { + const { deployer } = await getNamedAccounts(); + + + + // aave wallet manager + // const dischargeInterface = (recipient: string, amount: BigInt) => { + // const ABI = ["function transfer(address recipient, uint256 amount)"]; + // const iface = new ethers.Interface(ABI); + // const cdata = iface.encodeFunctionData("transfer", [recipient, amount]); + + // return cdata; + // }; + + // const dischargeCallData = dischargeInterface(deployer, amountDeposit); + + // // Add executor + // await aaveManager.setController(deployer).then(tx => tx.wait()); + // const aDAI = await ethers.getContractAt('IERC20Detailed', adaiAddress); + // const balanceBefore = await aDAI.balanceOf.staticCall(deployer); + + // await aaveManager.executeForAccount( + // addressBook[chainId].protonC, + // tokenId, + // adaiAddress, + // 0, + // dischargeCallData, + // ).then(tx => tx.wait()); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); \ No newline at end of file diff --git a/test/ExecuteForUser.test.ts b/test/ExecuteForUser.test.ts new file mode 100644 index 0000000..5b81ef0 --- /dev/null +++ b/test/ExecuteForUser.test.ts @@ -0,0 +1,97 @@ +import { expect } from "chai"; +import { ethers, getNamedAccounts, network } from 'hardhat'; +import { addressBook } from "../utils/globals"; +import { ProtonC, IERC20Detailed, ChargedParticles, AaveWalletManager } from "../typechain-types"; + +describe('Execute calls', async function () { + // Contracts + let dai: IERC20Detailed; + let proton: ProtonC; + let chargedParticles: ChargedParticles; + let aaveManager: AaveWalletManager; + + // Addresses + let adaiAddress: string; + + // Signers + let deployer: string, receiver: string; + + let chainId: number; + + before(async () => { + const { deployer: deployerAccount, user1 } = await getNamedAccounts(); + deployer = deployerAccount; + receiver = user1; + }); + + beforeEach(async () => { + chainId = network.config.chainId ?? 80001; + + if (chainId != 80001) { + throw new Error('Only run ExecuteForUser.test under hardhat test fork network') + }; + + adaiAddress = addressBook[chainId].stakingTokens[0].aave + // set up proton + proton = await ethers.getContractAt('ProtonC', addressBook[chainId].protonC); + + // set up DAI + dai = await ethers.getContractAt('IERC20Detailed', addressBook[chainId].stakingTokens[0].address); + + chargedParticles = await ethers.getContractAt('ChargedParticles', addressBook[chainId].chargedParticles); + aaveManager = await ethers.getContractAt('AaveWalletManager', '0xa8BaA965C302F748197C25a5217fb5b7c7a8C678'); + }); + + it('Energize and remove', async() => { + // Mint a Proton + const tokenId = await proton.createBasicProton.staticCall(deployer, deployer, 'asdf'); + + const amountDeposit: BigInt = ethers.parseEther('.1'); + await dai.approve(addressBook[chainId].chargedParticles, amountDeposit.toString()).then(tx => tx.wait()); + + const energizeTx = await chargedParticles.connect(await ethers.getSigner(deployer)).energizeParticle( + addressBook[chainId].protonC, + tokenId, + 'aave', + await dai.getAddress(), + amountDeposit.toString(), + '0x0000000000000000000000000000000000000000' + ).then(tx => tx.wait()); + + // mass + const mass = await chargedParticles.baseParticleMass.staticCall( + addressBook[chainId].protonC, + tokenId, + 'aave', + await dai.getAddress(), + ); + + expect(mass).to.eq(amountDeposit); + + const dischargeInterface = (recipient: string, amount: BigInt) => { + const ABI = ["function transfer(address recipient, uint256 amount)"]; + const iface = new ethers.Interface(ABI); + const cdata = iface.encodeFunctionData("transfer", [recipient, amount]); + + return cdata; + }; + + const dischargeCallData = dischargeInterface(deployer, amountDeposit); + + // Add executor + await aaveManager.setController(deployer).then(tx => tx.wait()); + const aDAI = await ethers.getContractAt('IERC20Detailed', adaiAddress); + const balanceBefore = await aDAI.balanceOf.staticCall(deployer); + + await aaveManager.executeForAccount( + addressBook[chainId].protonC, + tokenId, + adaiAddress, + 0, + dischargeCallData, + ).then(tx => tx.wait()); + + const savedBalance = await aDAI.balanceOf.staticCall(deployer); + expect(balanceBefore).to.be.lessThan(savedBalance) + }); +}); diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 0000000..e69de29 diff --git a/utils/globals.ts b/utils/globals.ts index 8e65a38..123ed0e 100644 --- a/utils/globals.ts +++ b/utils/globals.ts @@ -4,6 +4,7 @@ interface StakingToken { address: string; multiplier: string; funding: string; + aave?: string; } interface AddressBook { @@ -14,6 +15,7 @@ interface AddressBook { tokenInfoProxy: string; ionx: string; lepton: string; + protonC: string; stakingTokens: Array; }; } @@ -27,6 +29,7 @@ export const addressBook: AddressBook = { 'tokenInfoProxy': '0xeF0D1DEDaAF0D9e4B868a049101a9DB1Ba1e50c5', 'ionx': '0x02D3A27Ac3f55d5D91Fb0f52759842696a864217', 'lepton': '0x3Cd2410EAa9c2dCE50aF6CCAb72Dc93879a09c1F', + 'protonC': '0xBb4Ddbc0E26d4E4ae838B12a832379295D5fD917', 'stakingTokens': [ // { id: 'DAI', address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', multiplier: '24500', funding: '10000' }, // Deployed // { id: 'USDC', address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', multiplier: '21750', funding: '10000' }, // Deployed @@ -44,6 +47,7 @@ export const addressBook: AddressBook = { 'tokenInfoProxy': '0x349eEF86Ea34A69D8B880D5Fd5F39a6d2a7DE716', 'ionx': '0x01b317bC5eD573FAa112eF64DD029F407CecB155', 'lepton': '0xe349557325164577Ded350A8cAB03159c728B9E7', + 'protonC': '0x59dde2EBe605cD75365F387FFFE82E5203b8E4cd', 'stakingTokens': [ { id: 'DAI', address: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', multiplier: '41000', funding: '10000' }, { id: 'USDC', address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', multiplier: '42850', funding: '10000' }, @@ -58,6 +62,7 @@ export const addressBook: AddressBook = { 'tokenInfoProxy': '0x8fa84be9492aEA190d62d5f0fc11618d23a9ead2', 'ionx': '0xa817464e5faD7D5928739E1C37Ef845C53ab1eea', 'lepton': '0xa99294Caed407273A4b6320CaC68B27C58F46c5d', + 'protonC': '0x92971E5bB4d098CaCf2314292bDb5eDC3f5CF25e', 'stakingTokens': [ { id: 'DAI', address: '0x75Ab5AB1Eef154C0352Fc31D2428Cef80C7F8B33', multiplier: '71500', funding: '10000' }, ], @@ -69,6 +74,7 @@ export const addressBook: AddressBook = { 'chargedParticles': '0xaB1a1410EA40930755C1330Cc0fB3367897C8c41', 'chargedSettings' : '0x07DdB208d52947320d07E0E4611a80Fb7eFD001D', 'tokenInfoProxy': '0xeF0D1DEDaAF0D9e4B868a049101a9DB1Ba1e50c5', + 'protonC': '', 'lepton': '', 'ionx': '', 'stakingTokens': [ @@ -83,10 +89,11 @@ export const addressBook: AddressBook = { 'chargedParticles': '0x51f845af34c60499a1056FCDf47BcBC681A0fA39', 'chargedSettings' : '0x60428D3e580907C74Ee8690E4E192317864aAE1d', 'tokenInfoProxy': '0xda8d21714ea5784d5b6990c170485effb9104883', + 'protonC': '0x56D0d2e232e73634E5E9aaAB5d1b2f2e68e062Bd', 'lepton': '', 'ionx': '', 'stakingTokens': [ - { id: 'DAI', address: '0x001b3b4d0f3714ca98ba10f6042daebf0b1b7b6f', multiplier: '20000', funding: '10000' }, // Do-Not-Modify: used in unit-tests + { id: 'DAI', address: '0x001b3b4d0f3714ca98ba10f6042daebf0b1b7b6f', multiplier: '20000', funding: '10000', aave: '0x639cB7b21ee2161DF9c882483C9D55c90c20Ca3e' }, // Do-Not-Modify: used in unit-tests { id: 'USDC', address: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23', multiplier: '20000', funding: '10000' }, // Do-Not-Modify: used in unit-tests ], } diff --git a/yarn.lock b/yarn.lock index 36dd4f8..5b3ea72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4789,6 +4789,19 @@ ethers@4.0.0-beta.3: uuid "2.0.1" xmlhttprequest "1.8.0" +ethers@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.6.4.tgz#f03a86effcd55e82aed96a2fb9a56a9febd3e3d5" + integrity sha512-r3myN2hEnydmu23iiIj5kjWnCh5JNzlqrE/z+Kw5UqH173F+JOWzU6qkFB4HVC50epgxzKSL2Hq1oNXA877vwQ== + dependencies: + "@adraffy/ens-normalize" "1.9.2" + "@noble/hashes" "1.1.2" + "@noble/secp256k1" "1.7.1" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + ethers@^4.0.32, ethers@^4.0.40: version "4.0.49" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" @@ -4840,19 +4853,6 @@ ethers@^5.0.13, ethers@^5.5.3, ethers@^5.7.1: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -ethers@^6.6.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.6.2.tgz#0b6131b5fa291fec69b7ae379cb6bb2405c505a7" - integrity sha512-vyWfVAj2g7xeZIivOqlbpt7PbS2MzvJkKgsncgn4A/1xZr8Q3BznBmEBRQyPXKCgHmX4PzRQLpnYG7jl/yutMg== - dependencies: - "@adraffy/ens-normalize" "1.9.2" - "@noble/hashes" "1.1.2" - "@noble/secp256k1" "1.7.1" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699"