Принимая эфир в умном контракте
Я пытаюсь создать простой умный контракт, чтобы научиться основательности и тому, как работает 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
}