如何将合同余额从内部功能转移到外部地址?

发布于 2025-02-01 21:59:21 字数 2279 浏览 3 评论 0原文

在本合同中,我致电Paywinner()一旦第三名参与者购买了票。 paywinner()是内部的,以避免任何外部呼叫,但是当它执行winneraddress.transfer(winnablebalance); 时,合同余额被发送到内部地址而不是对外部地址> winneraddress 。显然,burnleftbalance()也是如此。

我想要么不可能通过内部功能将合同持有的一部分转移到外部地址,因此我需要为此创建一个公共功能(但是我看不出我如何确定是合同本身, ),或者我缺少一些东西。

pragma solidity ^0.8.14;

contract Lottery {
  address payable public burnAddress = payable(0x0000000000000000000000000000000000000000);
  uint256 public ticketsPerRound = 3;
  uint256 public ticketPrice = 0.001 * 10e8 * 10e8;
  address[] public participantAddresses;

  error WrongTicketPrice(uint256 expectedRole, uint256 actualRole);

  function buyTicket() external payable {
    if (msg.value != ticketPrice) {
      revert WrongTicketPrice(ticketPrice, msg.value);
    }

    participantAddresses.push(msg.sender);

    if (participantAddresses.length >= ticketsPerRound) {
      payWinner();
    }
  }

  function getBalance() external view returns (uint256) {
    return address(this).balance;
  }

  function getParticipantAddresses() external view returns (address[] memory) {
    return participantAddresses;
  }

  function getWinnableBalance() public view returns (uint256) {
    return address(this).balance / 2;
  }

  function getWinner() internal view returns (address payable winnerAddress) {
    uint256 unsafeRandomNumber = uint256(
      keccak256(abi.encodePacked(block.difficulty, block.timestamp, participantAddresses))
    );
    uint256 winnerIndex = unsafeRandomNumber % participantAddresses.length;
    winnerAddress = payable(participantAddresses[winnerIndex]);
  }

  function burnLeftBalance() internal {
    uint256 leftBalance = address(this).balance;

    burnAddress.transfer(leftBalance);

    reset();
  }

  function payWinner() internal {
    uint256 winnableBalance = getWinnableBalance();
    address payable winnerAddress = getWinner();

    winnerAddress.transfer(winnableBalance);

    burnLeftBalance();
  }

  function reset() internal {
    delete participantAddresses;
  }
}

In this contract, I call payWinner() once the third participant has bought a ticket. payWinner() is internal to avoid any external call but when it executes winnerAddress.transfer(winnableBalance);, the contract balance is sent to an internal address rather than to the external address winnerAddress. Same thing goes for burnLeftBalance() obviously.

I guess either it's impossible to transfer part of the contract holdings to an external address from an internal function and I need to create a public function for that (but I don't see how I can be sure that it's the contract itself calling the function), or there is something I'm missing.

pragma solidity ^0.8.14;

contract Lottery {
  address payable public burnAddress = payable(0x0000000000000000000000000000000000000000);
  uint256 public ticketsPerRound = 3;
  uint256 public ticketPrice = 0.001 * 10e8 * 10e8;
  address[] public participantAddresses;

  error WrongTicketPrice(uint256 expectedRole, uint256 actualRole);

  function buyTicket() external payable {
    if (msg.value != ticketPrice) {
      revert WrongTicketPrice(ticketPrice, msg.value);
    }

    participantAddresses.push(msg.sender);

    if (participantAddresses.length >= ticketsPerRound) {
      payWinner();
    }
  }

  function getBalance() external view returns (uint256) {
    return address(this).balance;
  }

  function getParticipantAddresses() external view returns (address[] memory) {
    return participantAddresses;
  }

  function getWinnableBalance() public view returns (uint256) {
    return address(this).balance / 2;
  }

  function getWinner() internal view returns (address payable winnerAddress) {
    uint256 unsafeRandomNumber = uint256(
      keccak256(abi.encodePacked(block.difficulty, block.timestamp, participantAddresses))
    );
    uint256 winnerIndex = unsafeRandomNumber % participantAddresses.length;
    winnerAddress = payable(participantAddresses[winnerIndex]);
  }

  function burnLeftBalance() internal {
    uint256 leftBalance = address(this).balance;

    burnAddress.transfer(leftBalance);

    reset();
  }

  function payWinner() internal {
    uint256 winnableBalance = getWinnableBalance();
    address payable winnerAddress = getWinner();

    winnerAddress.transfer(winnableBalance);

    burnLeftBalance();
  }

  function reset() internal {
    delete participantAddresses;
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

何以畏孤独 2025-02-08 21:59:21

没有“内部和外部地址”之类的东西。我能想到的最接近这个术语是外部拥有的帐户,这是一个术语代表从私钥派生的地址,没有合同字节的地址,主要由最终用户钱包使用。但这似乎与您的问题无关。

Etherscan使用“内部交易”作为“

因此,您发送的交易是您的地址, 的合同地址,value 0.01 ETH,其data /code>字段包含要执行的buyticket()函数的选择器...这些都是您发送的交易的所有参数。而“内部交易”只是一种显示交易产生的状态变化及其跟踪的一种方式。但是,只要产生了状态变化(例如,WinnerAddress>的增加平衡),如果它们是由“父级交易或“内部交易”产生的,则没有区别。

TLDR:这不是错误,这是一个功能。 :)

There's no such thing as "internal and external addresses". The closest to this term I can think of is Externally Owned Account, which is a term representing an address derived from a private key, without a contract bytecode, mostly used by end user wallets. But that does not seem to be related to your question.

Etherscan is using "internal transactions" as a more user-friedly term for "message calls within the virtual machine". These "internal transaction" details (such as from what sender, to what recipient, what data was passed, what ETH value, ...) are not part of the public blockchain data - only the combined state changes of the "parent" transaction are stored in the blockchain. So Etherscan retrieves these details by emulating the transaction, records its message calls and stores them in Etherscan's own database, and then displays them in a separate tab.

So, the transaction that you sent is from your address, to the contract address, with value of 0.01 ETH, its data field contains selector of the buyTicket() function that you want to execute... These are all params of the transaction that you sent. And the "internal transactions" are just a way of displaying state changes that your transaction produced, and their trace. But as long as the state changes were produced (e.g. increased balance of the winnerAddress), there's no difference if they were produced by a "parent" transaction or an "internal transaction".

TLDR: It's not a bug, it's a feature. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文