首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过坚固向Aave供应ETH

通过坚固向Aave供应ETH
EN

Stack Overflow用户
提问于 2021-07-28 00:02:47
回答 3查看 1.2K关注 0票数 4

我正在尝试存入Aave V2 Contract Aave代码示例

代码语言:javascript
复制
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 < 0.8.7;

import { IERC20, ILendingPool, IProtocolDataProvider, IStableDebtToken } from './Interfaces.sol';
import { SafeERC20 } from './Libraries.sol';

/**
* This is a proof of concept starter contract, showing how uncollaterised loans are possible
* using Aave v2 credit delegation.
* This example supports stable interest rate borrows.
* It is not production ready (!). User permissions and user accounting of loans should be implemented.
* See @dev comments
*/

contract MyV2CreditDelegation {
    using SafeERC20 for IERC20;
    
    ILendingPool constant lendingPool = ILendingPool(address(0x9FE532197ad76c5a68961439604C037EB79681F0)); // Kovan
    IProtocolDataProvider constant dataProvider = IProtocolDataProvider(address(0x744C1aaA95232EeF8A9994C4E0b3a89659D9AB79)); // Kovan
    
    address owner;

    constructor () public {
        owner = msg.sender;
    }

    /**
    * Deposits collateral into the Aave, to enable credit delegation
    * This would be called by the delegator.
    * @param asset The asset to be deposited as collateral
    * @param amount The amount to be deposited as collateral
    * @param isPull Whether to pull the funds from the caller, or use funds sent to this contract
    *  User must have approved this contract to pull funds if `isPull` = true
    * 
    */
    function depositCollateral(address asset, uint256 amount, bool isPull) public {
        if (isPull) {
            IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);
        }
        IERC20(asset).safeApprove(address(lendingPool), amount);
        lendingPool.deposit(asset, amount, address(this), 0);
    }

    /**
    * Approves the borrower to take an uncollaterised loan
    * @param borrower The borrower of the funds (i.e. delgatee)
    * @param amount The amount the borrower is allowed to borrow (i.e. their line of credit)
    * @param asset The asset they are allowed to borrow
    * 
    * Add permissions to this call, e.g. only the owner should be able to approve borrowers!
    */
    function approveBorrower(address borrower, uint256 amount, address asset) public {
        (, address stableDebtTokenAddress,) = dataProvider.getReserveTokensAddresses(asset);
        IStableDebtToken(stableDebtTokenAddress).approveDelegation(borrower, amount);
    }
    
    /**
    * Repay an uncollaterised loan
    * @param amount The amount to repay
    * @param asset The asset to be repaid
    * 
    * User calling this function must have approved this contract with an allowance to transfer the tokens
    * 
    * You should keep internal accounting of borrowers, if your contract will have multiple borrowers
    */
    function repayBorrower(uint256 amount, address asset) public {
        IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);
        IERC20(asset).safeApprove(address(lendingPool), amount);
        lendingPool.repay(asset, amount, 1, address(this));
    }
    
    /**
    * Withdraw all of a collateral as the underlying asset, if no outstanding loans delegated
    * @param asset The underlying asset to withdraw
    * 
    * Add permissions to this call, e.g. only the owner should be able to withdraw the collateral!
    */
    function withdrawCollateral(address asset) public {
        (address aTokenAddress,,) = dataProvider.getReserveTokensAddresses(asset);
        uint256 assetBalance = IERC20(aTokenAddress).balanceOf(address(this));
        lendingPool.withdraw(asset, assetBalance, owner);
    }
}

我有这样的代码:

代码语言:javascript
复制
App = {
  web3Provider: null,
  contracts: {},

  init: async function() {
    return await App.initWeb3();
  },

  initWeb3: async function() {
    // Modern dapp browsers...
    if (window.ethereum) {
      App.web3Provider = window.ethereum;
      try {
        // Request account access
        await window.ethereum.enable();
      } catch (error) {
        // User denied account access...
        console.error("User denied account access")
      }
    }
    // Legacy dapp browsers...
    else if (window.web3) {
      App.web3Provider = window.web3.currentProvider;
    }
    // If no injected web3 instance is detected, fall back to Ganache
    else {
      App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
    }
    web3 = new Web3(App.web3Provider);

    return App.initContract();
  },

  initContract: function() {
    $.getJSON('MyV2CreditDelegation.json', function(data) {
      // Get the necessary contract artifact file and instantiate it with @truffle/contract
      var safeYieldArtifact = data;
      App.contracts.MyV2CreditDelegation = TruffleContract(safeYieldArtifact);
    
      // Set the provider for our contract
      App.contracts.MyV2CreditDelegation.setProvider(App.web3Provider);
    });
    

    

    return App.bindEvents();
  },

  bindEvents: function() {
    $(document).on('click', '.btn-deposit', App.handleDeposit);
    $(document).on('click', '.btn-withdrawl', App.handleWithdrawl);
  },

  handleDeposit: function(event) {
    event.preventDefault();
    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }
    
      var account = accounts[0];

      App.contracts.MyV2CreditDelegation.deployed().then(function(instance) {
        creditDelegatorInstance = instance;
        const mockETHAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
        // Execute adopt as a transaction by sending account
        return creditDelegatorInstance.depositCollateral(mockETHAddress, 1, true);
      }).then(function(result) {
        //return App.markAdopted();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleWithdrawl: function(event) {
    event.preventDefault();
  },
};

$(function() {
  $(window).load(function() {
    App.init();
  });
});

当尝试提供时,Metamask会显示一个错误:

警报:事务错误。在合同代码中引发的异常。

只需一个简单的按钮就可以在html中调用它:

代码语言:javascript
复制
<button class="btn btn-default btn-withdrawl" 
  type="button"> Withdrawl
</button>

我在跑步

ganache-cli --fork https://mainnet.infura.io/v3/{{MyProjectId}}

我在控制台中看到的唯一错误是:

事务处理: 0x9961f8a187c09fd7c9ebf803771fa161c9939268bb01552a1598807bcfdc13ff气体使用: 24813块号: 12905002块时间: Mon 71.262021 20:38:30格林尼治时间-0400(东部夏令时)运行时错误:恢复

我的猜测是,我并没有恰当地调用Web3的合同

如何以编程方式向aave提供Eth (或任何其他令牌)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-08-08 20:15:12

我在浏览器中使用了硬帽子来发送事务,而不是Web3,但是我成功了:

  • 我用了科万测试网络。
  • 我使用MyCrypto水龙头给我的测试地址一些ETH。
  • 我用Aave水龙头给了自己一些AAVE。
  • 我从Aave的代码示例中导入了合同。
  • 我运行了下面的脚本:

创建一个新的HardHat项目

代码语言:javascript
复制
npm init --yes
npm install --save-dev hardhat 
npm install @nomiclabs/hardhat-waffle 
npm install --save-dev "@nomiclabs/hardhat-ethers@^2.0.0" "ethers@^5.0.0" "ethereum-waffle@^3.2.0"
npx hardhat 
(follow the prompt)
代码语言:javascript
复制
import '@nomiclabs/hardhat-ethers';
import * as dotenv from 'dotenv';
import { LogDescription } from 'ethers/lib/utils';
import hre from 'hardhat';
import { IERC20__factory, MyV2CreditDelegation__factory } from '../typechain';

dotenv.config();

// Infura, Alchemy, ... however you can get access to the Kovan test network
// E.g. https://kovan.infura.io/v3/<project-id>
const KOVAN_JSON_RPC = process.env.KOVAN_JSON_RPC || '';
if (!KOVAN_JSON_RPC) {
    console.error('Forgot to set KOVAN_JSON_RPC in aave.ts or .env');
    process.exit(1);
}

// Test account that has Kovan ETH and an AAVE token balance
const AAVE_HOLDER = '';

async function main() {
    // Fork Kovan
    await hre.network.provider.request({
        method: 'hardhat_reset',
        params: [{ forking: { jsonRpcUrl: KOVAN_JSON_RPC } }],
    });

    // Act like AAVE_HOLDER
    await hre.network.provider.request({
        method: 'hardhat_impersonateAccount',
        params: [AAVE_HOLDER],
    });
    const signer = await hre.ethers.getSigner(AAVE_HOLDER);
    console.log('signer:', signer.address);

    // AAVE token on Kovan network
    const token = IERC20__factory.connect('0xb597cd8d3217ea6477232f9217fa70837ff667af', signer);
    console.log('token balance:', (await token.balanceOf(signer.address)).toString());

    const MyV2CreditDelegation = new MyV2CreditDelegation__factory(signer);
    const delegation = await MyV2CreditDelegation.deploy({ gasLimit: 1e7 });
    console.log('delegation:', delegation.address);

    await token.approve(delegation.address, 1000000000000);
    console.log('allowance:', (await token.allowance(signer.address, delegation.address, { gasLimit: 1e6 })).toString());

    const depositTrans = await delegation.depositCollateral(token.address, 1000000000000, true, { gasLimit: 1e6 });
    console.log('depositTrans:', depositTrans.hash);
    const receipt = await depositTrans.wait();
    for (const log of receipt.logs) {
        const [name, desc] = parseLog(log) || [];
        if (desc) {
            const args = desc.eventFragment.inputs.map(({ name, type, indexed }, index) =>
                `\n    ${type}${indexed ? ' indexed' : ''} ${name}: ${desc.args[name]}`);
            args.unshift(`\n    contract ${name} ${log.address}`);
            console.log('Event', log.logIndex, `${desc.name}(${args ? args.join(',') : ''})`);
        } else {
            console.log('Log', log.logIndex, JSON.stringify(log.topics, null, 4), JSON.stringify(log.data));
        }
    }

    function parseLog(log: { address: string, topics: Array<string>, data: string }): [string, LogDescription] | undefined {
        try { return ['', delegation.interface.parseLog(log)]; } catch (e) { }
        try {
            const desc = token.interface.parseLog(log);
            return [log.address.toLowerCase() === token.address.toLowerCase() ? 'AAVE' : 'IERC20', desc];
        } catch (e) { }
    }
}

main().then(() => process.exit(0), error => {
    console.error(JSON.stringify(error));
    console.error(error);
});

其结果是:

代码语言:javascript
复制
$ hardhat run --no-compile --network kovan .\scripts\Aave.ts
token balance: 999999000000000000
delegation: 0x2863E2a95Dc84C227B11CF1997e295E59ab15670
allowance: 1000000000000
depositTrans: 0x0a3d1a8bfbdfc0f403371f9936122d19bdc9f3539c34e3fb1b0a7896a398f923
Done in 57.11s.

您可以在科万的以太扫描上验证它(第26666177、26666180和26666183块):

  • 部署MyV2CreditDelegation (事务合同)
  • AAVE (事务) 批准合同
    • 记录的Approval事件和token.allowance返回正确的值

  • 存款抵押品(事务)
    • 0.000001 AAVE从我的地址转移到已部署的合同
    • 0.000001 aAAVE从我的地址转移到已部署的合同
    • 0.000001 AAVE从部署合同转移到aAAVE合同
    • 为Transfer/Approval/Mint/DelegatedPowerChanged/...记录的多个事件

最初,我的脚本将首先部署一个测试令牌(并在它上给我一些余额),我会尝试将其作为抵押品存入,但是提供者以某种方式恢复了它,甚至没有在Kovan Etherscan上出现一个事务。因此,您的代码中的问题可能是mockETHAddress,而且您似乎并没有实际批准您的委托合同来提取指定的金额。

这个储存库中有一个更复杂但可以随时运行的安装程序。它模拟一个帐户,有一个ETH和AAVE余额在科万。

票数 3
EN

Stack Overflow用户

发布于 2022-09-05 05:17:20

如果有人在寻找如何在稳固契约中与Aave V3集成,下面是一个示例。

下面是一个简单的智能契约,允许您向Aave提供ERC20令牌抵押品,并获取可变利率贷款。

以下是您可以测试智能契约的方法:

  1. Aave水龙头获得测试USDC (确保您的钱包在Goerli网络上)。
  2. 将此智能契约部署到Goerli网络。
  3. 将一些测试USDC发送到您刚刚部署的契约地址。
  4. 调用supply()函数。
  5. 调用the ()函数。
代码语言:javascript
复制
// contracts/AaveExample.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma abicoder v2;

import "@aave-protocol/interfaces/IPool.sol";
import "@openzeppelin-contracts/token/ERC20/IERC20.sol";

contract Aave {

    // Storage Variables
    address public borrowTokenAddress = 0xDF1742fE5b0bFc12331D8EAec6b478DfDbD31464; // Goerli Aave DAI
    address public supplyTokenAddress = 0xA2025B15a1757311bfD68cb14eaeFCc237AF5b43; // Goerli Aave USDC
    address public aavePoolAddress = 0x368EedF3f56ad10b9bC57eed4Dac65B26Bb667f6;    // Goerli Aave Pool Address


    constructor() {}
    
    function supply() public returns (bool) {
        // 1. Set amountToDrain to the contract's supplyTokenAddress balance
        uint amountToDrain = IERC20(supplyTokenAddress).balanceOf(address(this));

        // 2. Approve Aave pool to access amountToDrain from this contract 
        IERC20(supplyTokenAddress).approve(aavePoolAddress, amountToDrain);

        // 3. Supply amountToDrain to Aave pool
        IPool(aavePoolAddress).supply(supplyTokenAddress, amountToDrain, address(this), 0);

        return true;
    }

    function borrow() public returns (bool) {
        // Borrow 0.3 DAI
        IPool(aavePoolAddress).borrow(borrowTokenAddress, 0.3 ether, 2, 0, address(this));

        return true;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2022-09-26 07:57:16

如果您只想使用稳健性向Aave贷款池提供ETH,那么有一个更好的方法。Aave有一个自动转换ETH到WETH和WETH到ETH的WETH网关,当你想退出的时候。

您将需要WETH网关接口、IERC20接口和aWETH (Aave兴趣令牌)接口来使其工作。

aWeth令牌的目的是跟踪您向贷款池提供的资金。当您在WETH网关上调用withdrawETH()函数时,它们会被WETH网关烧坏。

我写了一个详细的关于如何做它的指南

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68552918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档