Solidity:TypeError:函数声明为视图,但此表达式修改了状态,因此需要不可支付(默认)或应付

Posted

技术标签:

【中文标题】Solidity:TypeError:函数声明为视图,但此表达式修改了状态,因此需要不可支付(默认)或应付【英文标题】:Solidity: TypeError: Function declared as view, but this expression modifies the state and thus requires non-payable (the default) or payable 【发布时间】:2021-07-31 16:01:41 【问题描述】:

我一直在尝试创建一个智能合约/代币,将其部署在币安智能链测试网上。我遵循了一些文档并从这个开始。我正在研究这个功能问题。函数被声明为只读。这是源代码

该函数正在更改所有者地址的状态,还有什么选项可以将其声明为只读


// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.2;

//import "Context.sol";
//import "IBEP20.sol";
//import "SafeMath.sol";
//import "Ownable.sol";

contract SampleTaken 
    
    
    mapping(address => uint) public balances;
    
    uint public totalSupply = 1000000 * 10 ** 18;
    string public name ="Sample Token";
    string public symbol ="KJA";
    uint public decimals = 18;
    
    /** Events aailable for the Contract**/
    
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    
    constructor()
        balances[msg.sender] = totalSupply;
    
    
    function balanceOf(address _ownerAddress) public view returns (uint)
        return balances[_ownerAddress];
    
    
    function transfer(address _toAddress, uint _noOfTokens) public view returns (bool)
    require(balanceOf(msg.sender) >= _noOfTokens, "Total balance is less than the number of Tokens asked for !!!");
    balances[_toAddress] +=_noOfTokens;
    balances[msg.sender] -= _noOfTokens;
    emit Transfer(msg.sender,_toAddress, _noOfTokens);
    return true;
    
    
    function transferFrom(address _from, address _to, uint _value) public returns (bool)
     require(balanceOf(_from) >= _value, "Balance is less than the number of Tokens asked for !!!");
    // require(allowance[_from][msg.sender] >= _value, "Allowance too low");
     balances[_to] += _value;
     balances[_from] -= _value;   
     
     emit Transfer (_from, _to, _value);
     return true;
     
         

非常感谢任何帮助。

问候

【问题讨论】:

【参考方案1】:

从函数声明中删除viewpure关键字,只保留public returns

改变

function transfer(address _toAddress, uint _noOfTokens) public view returns (bool)

function transfer(address _toAddress, uint _noOfTokens) public returns (bool)

改变方法:

function transfer(address _toAddress, uint _noOfTokens) public returns (bool)
    require(balanceOf(msg.sender) >= _noOfTokens, "Total balance is less than the number of Tokens asked for !!!");
    balances[_toAddress] +=_noOfTokens;
    balances[msg.sender] -= _noOfTokens;
    emit Transfer(msg.sender,_toAddress, _noOfTokens);
    return true;
    
    

【讨论】:

【参考方案2】:

您的transfer() 函数被声明为view 函数。

函数可以声明为视图,在这种情况下它们承诺不会修改状态。

来源:Solidity docs

但是这些行(在transfer() 函数内)修改了状态:

balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);

如果您希望您的函数修改状态,它不能是 view(也不能是 pure)函数 - 您需要删除 view 修饰符:

function transfer(address _toAddress, uint _noOfTokens) public returns (bool)

【讨论】:

谢谢彼得。通过文档,看起来在这种情况下不能使用 View。但是,根据我的理解,将函数声明为视图会使它们无法从合同外部访问,从而保护了函数。我的理解不正确吗?谢谢 @user3161840 “视图使它们无法从合约外部访问” - 这是不正确的......如果您想限制哪些地址可以执行该功能,您可以使用ownable 方法。 OpenZeppelin 实现仅针对一个地址(存储在 _owner 属性中)进行验证,但您也可以针对多个地址(存储在数组或映射中)进行验证...如果您不希望任何其他合约或用户执行函数,需要标记为privateinternal

以上是关于Solidity:TypeError:函数声明为视图,但此表达式修改了状态,因此需要不可支付(默认)或应付的主要内容,如果未能解决你的问题,请参考以下文章

以太坊 solidity 函数的完整声明格式

03-Solidity8.0变量

Solidity BEP20:此时 transferFrom 未(或尚未)声明或可见

solidity之函数参数和返回变量

深入solidity内部 -以太坊EVN插槽存储关系

区块链 以太坊 solidity 什么时候使用storagememory