solidity learning (2)

一些小补充:

1.完全等价于如下三种形式:
    •    if(msg.sender != owner) { revert(); } 

    •    assert(msg.sender == owner); 

    •    require(msg.sender == owner); 正确才可往下走
(1)
revert() 和 require() 都会返还剩余 gas,而且允许返回一个数值:
revert(‘Something bad happened’);
或者
require(condition, ‘Something bad happened’);

(2)以下场景使用 require() :
    •    验证用户输入,即: require(input<20);
    •    验证外部合约响应,即: require(external.send(amount));
    •    执行合约前,验证状态条件,即: require(block.number > SOME_BLOCK_NUMBER) 或者 require(balance[msg.sender]>=amount)
    •    一般地,尽量使用 require 函数
    •    一般地,require 应该在函数最开始的地方使用
在我们的智能合约最佳实践中有很多使用 require() 的例子供参考。
以下场景使用 revert() :
    •    处理与 require() 同样的类型,但是需要更复杂处理逻辑的场景
如果有复杂的 if/else 逻辑流,那么应该考虑使用 revert() 函数而不是require()。记住,复杂逻辑意味着更多的代码。
以下场景使用 assert():
    •    检查 overflow/underflow,即:c = a+b; assert(c > b)
    •    检查非变量(invariants),即:assert(this.balance >= totalSupply);
    •    验证改变后的状态
    •    预防不应该发生的条件
    •    一般地,尽量少使用 assert 调用
    •    一般地,assert 应该在函数结尾处使用
基本上,require() 应该被用于函数中检查条件,assert() 用于预防不应该发生的情况,但不应该使条件错误。
另外,“除非认为之前的检查(用 if 或 require )会导致无法验证 overflow,否则不应该盲目使用 assert 来检查 overflow”——来自于@chriseth
2.函数中pure\view的区别
(1)view是不能修改状态(相当于constant)
下面的情况被认为是修改状态:
1. 写入状态变量;
2. (emitting??)发送事件;
3. 创建其他合约;
4. 使用selfdestruct;
5. 通过调用发送Ether;
6. 调用没有被声明为view和pure的函数
7. 使用低级调用;
8. 使用包含特定操作码的内联程序集。

(2)pure的限制更多一点,它是不能修改状态也不能读
除了上面列出的情况,下面的情况也被认为是有读和修改状态的行为:
1. 读取状态变量;
2. 访问this.balance 或者<address>.balance;
3. 访问block,tx,msg(除了msg.sig和msg.data);
4. 调用没有标记为pure的函数;
5. 使用包含特定操作码的内联程序集。


3.必须要带上payable关键字,这样才能正常接收msg.value

4.solidity的时间怎么设置
Solidity 还包含秒(seconds),分钟(minutes),小时(hours),天(days),周(weeks) 和 年(years) 等时间单位。

uint lastUpdated;//声明,为uint变量

// 将‘上次更新时间’ 设置为 ‘现在’
function updateTimestamp() public {
  lastUpdated = now;
}

加法是:lastUpdated + 5 minutes

5.solidity msg.sender.transfer
这句话的意思是,当我们在合同中有写payable的函数的时候,当调用这个函数是,msg.sender就需要付一定的msg.value,在这里,这个msg.value的去向to是合约的地址,但是一般在函数中,该value最终应该是会流向某一个账户的地址的,所以在这里我们一般都会定义一个数组来存放这个值value,当最后想要把这个值给一个账户地址的时候,我们就会使用语句msg.sender.transfer(value)来将合约地址上的这笔钱转到msg.sender这个账户地址中去

6.Warning: Variable is declared as a storage pointer. Use an explicit "storage" keyword to silence this warning.

解决办法是: 加一个显式声明storage(搞清楚其与memory的区别)
Bid storage exist = bidForPicture[pictureId];



7.now (uint): 当前块的时间戳(block.timestamp的别名)
localhost/new/myToken.sol:63:17:use of "now": "now" does not mean current time. Now is an alias for block.timestamp. Block.timestamp can be influenced by miners to a certain degree, be careful.

8.
Gas requirement of function CryptoPicturesMarket.imageHash() high: infinite. If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)
但是我查了一下资料,发现这个好像不是什么问题,希望以后能够看到可以解决它的方法吧

9.声明一个类型为 uint (256位无符号整数)
所以在solidity中,如果你声明了一个变量类型是uint的,其实就是声明了一个uint256的

10.自毁¶
合约代码从区块链上移除的唯一方式是合约在合约地址上的执行自毁操作 selfdestruct 。合约账户上剩余的以太币会发送给指定的目标,然后其存储和代码从状态中被移除。
尽管一个合约的代码中没有显式地调用 selfdestruct ,它仍然有可能通过 delegatecall 或 callcode 执行自毁操作。

11.当你 安装了solc后,如果你想要查看它的信息的话,你要运行的语句是:
npm install -g solc
solcjs —help(而不是solc —help)


12.当需要按顺序加入内容的时候,也不一定要使用mapping,而是可以使用数组:
struct Proposal{…}
 // 一个 `Proposal` 结构类型的动态数组
    Proposal[] public proposals;

猜你喜欢

转载自www.cnblogs.com/wanghui-garcia/p/9496587.html