测试包含transferFrom的函数时,我的代码正在还原。还原被隔离到此行,注释掉后,它运行良好。

到目前为止,我的(错误的)假设是:

  • 发出批准 token (错误的from地址或错误的Loan合同地址?)
  • 将错误的this.Token.address传递给createLoan

  • 关于可能还有其他问题的任何想法?

    这是我的合同Loan.sol
    pragma solidity ^0.5.0;
    
    import "openzeppelin-solidity/contracts/math/SafeMath.sol";
    import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
    import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
    import "./DSmath.sol";
    
    contract Loan is Ownable, DSMath {
    
    ...
    function createLoan
        (
            uint _loanAmount,
            uint _collateralAmount,
            address _collateralAddress
        )
        external {
            require(loaneeToDebt[msg.sender] == 0, "User already owes tokens");
            require
            (
                isCollateralized(_loanAmount, _collateralAmount, _collateralAddress),
                "Collateral posted is insufficient to receive a loan"
            );
            require(tokenPrices[_collateralAddress] != 0, "Collateral token not registered to system");
    
            ERC20(_collateralAddress).transferFrom(msg.sender, address(this), _collateralAmount); //REVERTS HERE
    
            loaneeToDebt[msg.sender] = _collateralAmount;
    
        }
    

    我正在Loan.test.js中像这样测试:
    // Loan.test.js
    const {BN, expectEvent, shouldFail, constants} = require("openzeppelin-test-helpers");
    const Loan = artifacts.require("Loan");
    const ERC20Mock = artifacts.require("ERC20Mock")
    
    contract("Loan", function ([_, contractOwner, user]) {
    
        const initialSupply = new BN(1).mul(new BN(10).pow(new BN(28)))
        beforeEach(async function () {
            this.Loan = await Loan.new({from: contractOwner});
            this.Token = await ERC20Mock.new(user, initialSupply)
        });
    
        describe("#createLoan", function () {
            const collateralAmount = new BN(5).mul(new BN(10).pow(new BN(27)))
            const loanAmount = new BN(1).mul(new BN(10).pow(new BN(24)))
            const tokenPrice = new BN(1)
            beforeEach(async function () {
                await this.Loan.setTokenPrice(this.Token.address, tokenPrice, {from: contractOwner});
            });
    
            it("should revert if the user has an outstanding loan", async function () {
                await this.Token.approve(this.Loan.address, collateralAmount, {from: user}); // APPROVAL
                await this.Loan.createLoan(loanAmount, collateralAmount, this.Token.address, {from: user}) // REVERTS HERE
                shouldFail.reverting(this.Loan.createLoan(loanAmount, collateralAmount, this.Token.address, {from: user});
            });
        });
    });
    

    ERC20Mock:
    pragma solidity ^0.5.0;
    import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
    
    contract ERC20Mock is ERC20 {
        constructor (address initialAccount, uint256 initialBalance) public {
            _mint(initialAccount, initialBalance);
        }
    
        function mint(address account, uint256 amount) public {
            _mint(account, amount);
        }
    
        function burn(address account, uint256 amount) public {
            _burn(account, amount);
        }
    
        function burnFrom(address account, uint256 amount) public {
            _burnFrom(account, amount);
        }
    }
    

    最佳答案

    为了能够进行transferFrom,需要在批准用户之前。

      function approve(address spender, uint256 value) external returns (bool);
    

    在您的情况下,消息发件人应批准与_collat​​eralAmount相同金额的贷款合同。

    您也可以使用以下功能检查一个人有多少津贴:
      function allowance(address owner, address spender) external view returns (uint256);
    

    值得在createLoan()的开头提出一个要求,以检查配额是否足够。

    关于solidity - 在ERC20.transferFrom上还原,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54348232/

    10-09 22:21