Принимая эфир в умном контракте

Я пытаюсь создать простой умный контракт, чтобы научиться основательности и тому, как работает Ethereum.

Из того, что я понимаю, использование метода модификации, подлежащего оплате, заставит его принять значение. Затем вычитаем из отправителя и добавляем, что где-то еще, в этом коде я пытаюсь отправить его владельцу договора.

contract  AcceptEth {
    address public owner;
    uint public bal;
    uint public price;
    mapping (address => uint) balance;

    function AcceptEth() {
        // set owner as the address of the one who created the contract
        owner = msg.sender;
        // set the price to 2 ether
        price = 2 ether;
    }

    function accept() payable returns(bool success) {
        // deduct 2 ether from the one person who executed the contract
        balance[msg.sender] -= price;
        // send 2 ether to the owner of this contract
        balance[owner] += price;
        return true;
    }
}

Когда я взаимодействую с этим контрактом через ремикс, я получаю сообщение об ошибке "Исключение виртуальной машины при обработке транзакции: из газа", при этом создается транзакция, цена на газ которой составляет 21000000000, а значение 0,00 ETH, когда я пытаюсь получить 2 эфира. от любого, кто выполняет этот метод.

Что не так с кодом? В качестве альтернативы я могу добавить переменную для одного для ввода значения, которое они хотят отправить, вместе с методом изъятия, верно? но ради обучения я хотел, чтобы все было просто. но даже этот код кажется немного простым и кажется, что чего-то не хватает.

1 ответ

Решение

Я думаю, что вы заблудились в том, что контракты встроили механизмы для получения и хранения эфира. Например, если вы хотите, чтобы ваш accept() метод получает ровно 2 эфира (или то, что вы установили price к), вы бы сделали что-то вроде этого:

contract  AcceptEth {
    address public owner;
    uint public price;
    mapping (address => uint) balance;

    function AcceptEth() {
        // set owner as the address of the one who created the contract
        owner = msg.sender;
        // set the price to 2 ether
        price = 2 ether;
    }

    function accept() payable {
        // Error out if anything other than 2 ether is sent
        require(msg.value == price);

        // Track that calling account deposited ether
        balance[msg.sender] += msg.value;
    }
}

Теперь предположим, что у вас есть два аккаунта со следующими балансами:

0x01 = 50 эфира

0x02 = 20 эфира

И этот контракт развернут и имеет адрес 0xc0. Все адреса могут содержать эфир, поэтому даже в самом договоре есть баланс. Поскольку он был только развернут (и не был развернут ни с каким начальным эфиром), его баланс равен 0.

Теперь скажите 0x01 звонков accept() отправка в 2 эфира. Транзакция будет выполнена, и 3 адреса в нашем примере будут иметь следующие балансы:

0x01 = 48 эфира

0x02 = 20 эфира

0xc0 = 2 эфира

Теперь, скажем, 0x02 звонков accept() ДВАЖДЫ, пропуская 2 эфира оба раза:

0x01 = 48 эфира

0x02 = 16 эфира

0xc0 = 6 эфира

Контракт содержит весь эфир, отправленный ему. Но ваш контракт также имеет состояние (balance карта, которую вы определили в коде), которая отслеживает, кто что внес на хранение. Итак, вы знаете из этого отображения, что 0x01 депонировал 2 эфира и 0x02 депонировал 4 эфира. Если вы хотите представить refund() метод, который отправляет эфир обратно, вы бы написали это так

function refund(uint amountRequested) public {
  require(amountRequested > 0 && amountRequested <= balance[msg.sender]);

  balance[msg.sender] -= amountRequested;

  msg.sender.transfer(amountRequested); // contract transfers ether to msg.sender's address
}
Другие вопросы по тегам