Вывод эфириума из смарт-контракта (возврат отправителю)

Допустим, у меня есть децентрализованное приложение, которое позволяет людям покупать какой-то объект по произвольной цене.

Пользователь 1 покупает объект за 1 eth. Через несколько мгновений пользователь 2 покупает тот же товар. Как я могу отслеживать это событие и автоматически возвращать соответствующее количество эфириума пользователю 2? Вот что у меня есть до сих пор:

contract Adoption {
    address[16] public adopters;

    function returnEth() public payable {
    msg.sender.transfer(msg.value);
    }
    // Adopting a pet
    function adopt(uint petId) public payable returns (uint) {
        require(petId >= 0 && petId <= 15);
        //require(msg.value == 1 ether);
        adopters[petId] = msg.sender;
        returnEth();
        return petId;
        //return value;
    }
    // Retrieving the adopters
    function getAdopters() public view returns (address[16]) {
        return adopters;
    }


}
Ваш второй вопрос не связан с первым. Я бы предложил задать его как новый вопрос. (Другим трудно извлечь пользу из вашего вопроса или ответить на него, если он скрыт внутри другого вопроса.)

Ответы (1)

Читая между строк, я думаю, вы говорите, что пользователю 2 не должно быть разрешено покупать товар, который уже купил пользователь 1.

Если это так, то звонок, сделанный пользователем 2 для покупки предмета, должен завершиться ошибкой. Вы не поделились функцией, которая используется для совершения покупки, но она должна отменить транзакцию, если товар уже продан.

Что произойдет, если транзакция все еще подтверждается?
Транзакция, которая не была подтверждена, просто ждет. Это не имеет никакого эффекта. Когда он, наконец, будет обработан, он либо преуспеет (если он первым купит предмет), либо потерпит неудачу.
Это хорошая информация, но я все же хотел бы знать, как отправить эфир пользователям из контракта. Должен ли я обновить свой исходный вопрос?
Это просто <address>.transfer(<amount>).
Так будет ли мой исходный код теоретически работать, если он будет вызван в нужное время?
Для вашего исходного кода, если пользователь А отправляет 1 эфир в функцию, то она передает 1 эфир пользователю А. Если по какой-то причине вы не хотите просто отменить транзакцию, то это кажется прекрасным способом вернуть переданные средства. эфир.
хорошо. Если бы я хотел вызвать эту функцию внутри своего контракта (та же самая, на которую вы ответили на мой последний вопрос), как бы я сделал это с помощью web3js? Я просто не хочу спамить StackExchange вопросами.
Чтобы вызвать его из другой функции в вашем контракте, просто выполните returnEth();. Если ваш вопрос: «Как мне вызвать функцию из web3.js?» это не кажется связанным. Пожалуйста, задайте его как новый вопрос, но сначала просто прочитайте учебник, может быть, даже мой: programtheblockchain.com/posts/2017/12/13/… . (Я думаю, однако, что, может быть, вы используете Truffle? Если да, посмотрите вместо этого учебник.)
поэтому я больше не буду говорить о web3js, но если я вызову returnEth(); в моем существующем контракте eth вычитается из моего кошелька метамаски, но не возвращается. Вы знаете, почему это может происходить?
Нет. Прямой вызов returnEth()никогда не должен уменьшать количество эфира на счету вызывающего абонента. Даже если это transferне удастся, транзакция будет отменена, поэтому эфир не будет двигаться.
1 eth вычитается из их кошелька с помощью функции accept() в моем предыдущем вопросе. returnEth() вызывается из accept(), но, похоже, он не работает.
Вам нужно будет поделиться фактическим кодом, который вы используете (я думаю, текущий код для adoptэтого вызывает returnEth.)
обновил мой вопрос полным кодом
Код в вашем вопросе отлично работает для меня. Обратите внимание, что плата за газ взимается независимо ни от чего, поэтому баланс эфира на счете должен уменьшаться на небольшую сумму с каждой транзакцией. Но если я начну со 100 эфиров и отправлю 1 эфир на adopt(), после звонка я получу> 99,99999999 эфиров.