https://solidity.readthedocs.io/en/develop/contracts.html#visibility-and-getters
- 可见性参考:http://www.tryblockchain.org/Solidity-VisibilityandAccessors-可见性和访问控制器.html
- Solidity中有两种函数调用方式
-
internaldo not create an actual EVM call (also called a “message call”)- 合约内部的函数之间可以直接调用。比如在
contract C中定义了两个函数g()和f(uint),在g中可以直接return f(5)+g(); - 这种函数调用在EVM中被解析为简单的
jump,即需要的变量也好,代码也好,已经加载到memory中了;
- 合约内部的函数之间可以直接调用。比如在
-
external会创建实际的EVM调用(消息调用)- 比如
this.f(3); contractInstance.g();而f(3)则不可以。此时是消息调用,不是jump。this不可以使用在构造函数中,因为合约实例还没有被创建。
- 比如
-
对 function 和 状态变量 的四种类型可见性,其中函数默认是public,状态变量默认是internal
-
external:外部的- 可以由其他合约或者交易发起调用(只能通过
external方式调用) - 不可以被内部调用,如
f();,但是可以this.f(); - 外部函数有时候在接收到大的数组数据时比较有效
- 可以由其他合约或者交易发起调用(只能通过
-
public:公共的- 内部调用 或者 通过消息(即
external和internal两种调用方式) - 对于
public的状态变量,会自动的生成getter函数。这个函数是外部external可见的。当在内部访问的时候,即不使用this,相当于状态变量。当外部访问的时候,如this.data(),则等价于函数。- 对于数组类型的
public状态变量,则可以使用getter的作用只返回一个元素,而不是整个数组,从而节省gas。
- 对于数组类型的
- 内部调用 或者 通过消息(即
-
internal:内部的- 只能内部访问,即从当前合约或者派生合约
- 不用
this
-
private:私有的- 只能在定义的合约中使用,不能在派生合约中使用
-
external和public在external方式调用下的区别是:public更昂贵,需要花费的gas要多一些,因为需要把参数都拷贝到memory中,而external可以直接使用calldata.
值得注意的是:区块链外部的人可以看到区块链上的所有东西。私有的private仅仅是防止其他合约访问和修改信息。对区块链外面的世界依然是完全可见的。
- 外部可见性定义方式
- 对于变量
变量类型 可见性 变量名; - 对于函数
function 函数名(形参类型 形参名)可见性 returns(返回值类型 返回变量名)
- 对于变量
pragma solidity >=0.4.0 <0.7.0;
contract C {
uint private data;
function f(uint a) private pure returns(uint b) { return a + 1; }
function setData(uint a) public { data = a; }
function getData() public view returns(uint) { return data; }
function compute(uint a, uint b) internal pure returns (uint) { return a + b; }
}
// This will not compile
contract D {
function readData() public {
C c = new C();
uint local = c.f(7); // error: member `f` is not visible
c.setData(3);
local = c.getData();
local = c.compute(3, 5); // error: member `compute` is not visible
}
}
contract E is C {
function g() public {
C c = new C();
uint val = compute(3, 5); // access to internal member (from derived to parent contract)
}
}
modifier:- 改变函数的行为
- 在函数执行之前自动检查环境
- 是合约中可以被继承的部分。可以被派生类的合约重载。
modifier 名称{
require(
相当于执行某个函数之前需要判断的一些条件,if()这种
);
_; //使用这个modifier的函数在判断完上面的条件之后,就把函数插入到这里来执行。
}
function 函数名() modifier的名称,可见性 returns(){
...
}
fallback函数:当接收到合约调用,没有其他的函数可以匹配的时候执行。相当于一个默认函数。可以使用payable,这个函数可以把发来交易中的ether存入合约。如果函数体中没有对ether做任何处理,那这笔ether将无法被提取。- 合约中唯一一个没有名字的函数
- 没有参数,没有返回值。但是参数中可以包含
mag.data,用来检索调用中提供的payload。 - 必须是
external的可见性
没有fallback函数的合约,在收到ether时,会作为创世交易(coinbase transaction)的接收方,或者作为selfdestruct(自毁)的目的地。
-
msg.data(uint):complete calldata -
msg.sender(address):sender of the message (current call) -
tx.origin(address):sender of the transaction (full call chain) -
msg.value(uint):number of wei sent with the message -
assert(bool condition):- invalidates the transaction if the condition is not met - to be used for internal errors.
-
require(bool condition):- reverts if the condition is not met - to be used for errors in inputs or external components.
-
require(bool condition, string message):- reverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message.
-
iterative_mapping使用方法参考:https://medium.com/rayonprotocol/creating-a-smart-contract-having-iterable-mapping-9b117a461115
本文深入探讨Solidity中合约函数及状态变量的可见性控制,包括internal、external、public和private的区别,以及如何正确使用这些修饰符来保护合约的安全。同时,文章还介绍了modifier的使用,以及fallback函数的作用。

2469

被折叠的 条评论
为什么被折叠?



