【Solidity】支付

以太比的单位

wei、gwei、finney 和 ether 是以太币(Ether)的不同单位。

  1. wei 是以太币的最小单位,1 ether = 10^18 wei;这是 Solidity 中的默认单位
solidity 复制代码
uint public oneWei = 1 wei;
  1. gwei 是 wei 的 10^9 倍,1 ether = 10^9 gwei;常用于表示交易费用 (gas price)
solidity 复制代码
uint public oneGwei = 1 gwei;
  1. finney 是 wei 的 10^15 倍,1 ether = 10^3 finney
solidity 复制代码
uint public oneFinney = 1 finney;
  1. ether 是 wei 的 10^18 倍;是以太坊的基本单位
solidity 复制代码
uint public oneEther = 1 ether;

payable 修饰符

以下函数需要使用 payable 修饰:① 需要接收以太币的函数;② 需要使用 msg.value / callvalue() 且可被外部访问的函数。

solidity 复制代码
contract Demo {
    // 使用 payable 修饰构造函数,使合约可以在部署时接收以太币
    constructor() payable {}

    // 接收以太币的函数, 必须使用 payable 修饰符
    function receiveEther() external payable {
        require(msg.value > 0, "Must send some Ether");
    }

    // 提现函数, 将合约中的以太币发送给调用者
    function withdraw() external {
        uint amount = address(this).balance;
        require(amount > 0, "No Ether to withdraw");
        payable(msg.sender).transfer(amount);
    }

    // 获取合约的以太币余额
    function getBalance() external view returns (uint) {
        return address(this).balance;
    }
}
  1. 设置以太币的数量,部署 Demo 合约

  2. 调用 getBalance 函数,查看合约的以太币余额

  3. 设置以太币的数量,调用 receiveEther 函数

  4. 调用 getBalance 函数,查看合约的以太币余额

  5. 调用 withdraw 函数,将合约中的以太币发送给调用者

  6. 再次调用 getBalance 函数,查看合约的以太币余额

receive & fallback 方法

在 Solidity 中,receive & fallback 是一种特殊的函数。它不需要 function 关键字、没有参数、也没有返回值。

特性:

  • receive & fallback 函数必须声明为 external,表示只能通过外部调用来触发。
  • receive 必须使用 payable 修饰符;fallback 可以使用 payable 修饰符。

receive & fallback 的区别:

  • receive:专门用于处理没有附加数据的以太币转账。
  • fallback:用于处理所有其他情况,包括调用不存在的函数或接收带有附加数据的以太币转账。如果合约没有定义 receive 方法,但定义了 payable 的 fallback 方法,那么在接收以太币时会调用 fallback 方法。
solidity 复制代码
contract Demo {
    event Log(string message, address sender, uint value, bytes data);

    // 定义 receive 方法
    receive() external payable {
        emit Log("receive", msg.sender, msg.value, "");
    }

    // 定义 fallback 方法
    fallback() external payable {
        emit Log("fallback", msg.sender, msg.value, msg.data);
    }
}

以太币的发送与接收

接收以太币的 3 种形式:

  1. 编写 payable receive / fallback 方法,以支持直接传入以太币

  2. 用 payable 修饰 constructor 方法,以支持在部署时传入以太币

  3. 用 payable 修饰其他方法,以支持在调用方法时传入以太币

solidity 复制代码
contract ReceiveEther {
    event Received(address, uint, uint);

    // 接收部署时传入的以太币
    constructor() payable {}

    // 接收直接传入的以太币
    receive() external payable {
        // 打印发送者、接收的以太币数量、剩余的 gas
        emit Received(msg.sender, msg.value, gasleft());
    }

    // 接收调用方法时传入的以太币
    function receiveEther() external payable {
        // 打印发送者、接收的以太币数量、剩余的 gas
        emit Received(msg.sender, msg.value, gasleft());
    }
}
  1. 设置以太币的数量,部署 ReceiveEther 合约;查看事件,可以看到接收的以太币数量

  2. 设置以太币的数量,调用 receiveEther 函数;查看事件,可以看到接收的以太币数量

用 payable 修饰的 address 变量有 3 个方法发送以太币:

  1. transfer:有 2300 gas 的限制;如果转账失败,会回滚交易

  2. send:有 2300 gas 的限制;如果转账失败,不会回滚交易,而是返回 false

  3. call:没有 gas 限制,可以指定 gas 量;如果转账失败,不会回滚交易,而是返回 false

solidity 复制代码
contract SendEther {
    // 使用 transfer 发送以太币
    function sendEtherViaTransfer(address payable recipient) external payable {
        recipient.transfer(msg.value);
    }

    // 使用 send 发送以太币
    function sendEtherViaSend(address payable recipient) external payable {
        bool success = recipient.send(msg.value);
        require(success, "Send failed");
    }

    // 使用 call 发送以太币 (推荐)
    function sendEtherViaCall(address payable recipient) external payable {
        (bool success, ) = recipient.call{value: msg.value}("");
        require(success, "Call failed");
    }
}
  1. 部署 SendEther 合约

  2. 设置以太币的数量,调用 SendEther 合约的 sendEtherViaTransfer 函数,传入 ReceiveEther 合约的地址;可以看到 ReceiveEther 合约的以太币余额变化

  3. 设置以太币的数量,调用 SendEther 合约的 sendEtherViaSend 函数,传入 ReceiveEther 合约的地址;可以看到 ReceiveEther 合约的以太币余额变化

  4. 设置以太币的数量,调用 SendEther 合约的 sendEtherViaCall 函数,传入 ReceiveEther 合约的地址;可以看到 ReceiveEther 合约的以太币余额变化

相关推荐
小树苗1931 天前
DePIN潜力项目Spheron解读:激活闲置硬件,赋能Web3与AI
人工智能·web3
CESS_Cloud1 天前
CESS 出席华盛顿区块链政策峰会:参与国家安全与数据隐私保护专题讨论
安全·阿里云·web3·去中心化·区块链
我可是千机伞3 天前
BOB.meme已于12月18日正式部署于BNB Chain
web3
TianXuan_Chain3 天前
web3跨链桥协议-Nomad
web3·区块链·智能合约·跨链桥
CertiK3 天前
Web3.0安全开发实践:探索比特币DeFi生态中的PSBT
区块链
选择不变3 天前
慢牛提速经典K线形态-突破下跌起始位和回档三五线,以及徐徐上升三种形态
区块链·通达信指标公式·炒股技巧·短线指标·炒股指标
飞天阁3 天前
Hyperledger Fabric 2.x 环境搭建
运维·区块链·fabric
Sui_Network3 天前
Sui 基金会任命 Christian Thompson 为新任负责人
大数据·人工智能·物联网·区块链·智能合约
电报号dapp1193 天前
NFT交易所开发攻略:打造未来数字艺术品交易新平台
人工智能·去中心化·区块链·智能合约
Q8137574603 天前
中阳动态分散投资策略:构建多元化投资组合的科学路径
人工智能·区块链