--- title: "Solidity in Short" date: 2022-04-07T11:10:45+07:00 draft: true --- ## `solc` 命令行 - `--asm` `--optimize --asm` - `--via-ir` ## 虛擬機(EVM) - uint: 256bit - address: 160bit - 成员访问不需要 this - 关键字 `public` 使变量可以从其他合约中访问 - `event` 允许客户端对您声明的特定合约变化做出反应 - 构造函数代码只有在合约创建时运行 - `error` 变量允许您提供关于操作失败原因的信息, 它们会返回给函数的调用者,与 `revert` 一起使用。 - `map` 自动初始化,不能获得所有键/值列表 - 交易总是由发送人(创建者)签名 - 如果您想安排您的合约的未来调用(timer),您可以使用智能合约自动化工具或oracle服务 - 在合约创建的过程中,它的代码还是空的。 所以直到构造函数执行结束,您都不应该在其中调用合约自己函数。 - 每笔交易都会被收取一定数量的 gas, 这些 gas 必须由交易的发起人(tx.origin)支付 - 每个区块都有最大 gas 量 - gas price 是交易发起人设定的值, 他必须提前向 EVM 执行器支付 gas_price * gas。 如果执行后还剩下一些 gas,则退还给交易发起人。如果发生撤销更改的异常,已经使用的 gas 不会退还 - 以太坊虚拟机有三个存储数据的区域:存储器,内存和堆栈 - 内存 读的宽度限制在256位, 而写的宽度可以是8位或256位 - 合约可以通过消息调用的方式来调用其它合约或者发送以太币到非合约账户 - 调用被 限制 在1024的深度;在一个消息调用中,只有63/64的gas可以被转发 - 委托调用(delegatecall), 除了目标地址的代码是在调用合约的上下文(即地址)中执行, msg.sender 和 msg.value 的值不会更改之外,其他与消息调用相同 - 合约甚至可以通过一个特殊的指令来创建其他合约 - 从区块链上删除代码的唯一方法是当该地址的合约执行 selfdestruct 操作, 存储在该地址的剩余以太币被发送到一个指定的目标,然后存储和代码被从状态中删除.如果有人向被删除的合约发送以太币,以太币就会永远丢失 - 尽管一个合约的代码中没有显式地调用 selfdestruct , 它仍然有可能通过 delegatecall 或 callcode 执行自毁操作。 - 有一小群合约地址是特殊的。 1 和(包括) 8 之间的地址范围包含 “预编译合约“ ## 语言 - 一个 pragma 指令始终是源文件的本地指令 - 单位 - 1 wei = 1 - 1 gwei = 1e9 - 1 ether = 1e18 - 函数修饰器 - virtual: 可重载 - ### 生僻关键字 - modifier - error - unchecked { ... } 切换到“不检查模式 - fixed/ufixed: 有/无符号的定长浮点型 - address - address 20byte - address payable: 与 address 相同,但有额外的方法 transfer 和 send - 允许从 address payable 到 address 的隐式转换, 而从 address 到 address payable 的转换必须通过 payable(
) 来明确 - 只有在合约可以接收以太的情况下才允许这种转换,也就是说, 合约要么有一个 receive 函数,要么有一个 payable 类型的 fallback 的函数 - delegatecall:只使用给定地址的代码, 所有其他方面(存储,余额,...)都取自当前的合约 - staticcall:基本上与 call 相同, 但如果被调用的函数以任何方式修改了状态,则会恢复。 - 所有的合约都可以转换为 address 类型,所以可以用 address(this).balance 查询当前合约的余额。 ## 全局变量 - msg - data - sender - sig - value - tx - origin - gasprice - block - basefee - chainid - coinbase - difficulty - gaslimit - number - timestamp - blockhash(unit blockNumber) returns (bytes32) - gasleft() returns (uint256) ## 合约 - 当一个合约被创建时,它的 构造函数(constructor) (一个用 constructor 关键字声明的函数)被执行一次。构造函数执行完毕后,合约的最终代码被存储在区块链上。部署的代码不包括构造函数代码或只从构造函数调用的内部函数。 - 状态变量可见性 - public - internal - private: 派生合约中是不可见 - 函数可见性 - external: 一个外部函数 f 不能从内部调用 (即 f() 不起作用,但 this.f() 可以)。 - public: - internal: - private: - constant, immutable 状态变量:对于 constant 变量,其值必须在编译时固定, 而对于 immutable 变量,仍然可以在构造时分配。 - 状态可变性 - view: 函数承诺不修改状态 - pure: 函数承诺不读取或修改状态 - 特殊函数 - 最多一个 `receive() external payable{}` 函数 - 最多一个 `fallback() external [payable]` 或 `fallback(bytes calldata input) external [payable] returns (bytes memory output)`