Судя по отзывам опытных наставников, здесьthrow
предлагается механизм . Я предполагаю, что механизм перехвата не существует для : https://ethereum.stackexchange.com/a/2512/4575 .throw
Исходя из этого, у меня есть проблема: сначала я должен проверить некоторые условия, которые могут иметь высокое значение газа. Если условие не throw
будет выполнено. Поэтому, если условие не выполняется, я хочу вернуть деньги клиенту. В противном случае деньги должны возвращаться кластеру.
[В] Если условие не выполняется, throw
произойдет. Поскольку throw
завершает код, у меня нет возможности поймать возвращенную версию и применить 1 строку кода для возврата денег клиенту. Есть ли альтернативное решение для решения этой проблемы?
Обратите внимание, что состояние изменится. Так что я должен сделать, throw
если есть условие не удается.
function payMeBack() {
if(require(<some condition>)) //if condition is wrong throw take place and never JUMPS to else side.
if(!client.send(gainedWei)) throw;
else
if(!cluster.send(gainedWei)) throw;
gainedWei = 0;
client.success = 1;
}
Спасибо за ваше драгоценное время и помощь.
Нет механизма захвата для броска. Состояние возвращается к состоянию до транзакции. Не обращайте внимания на порядок операций и даже операции, имевшие место в вызывающих контрактах. Throw
означает, что транзакция, исходящая от EOA, подписавшего транзакцию , не произошла (с некоторым побочным эффектом, что весь предоставленный газ был уничтожен).
Вы получаете синтез лучших практик, чтобы вы могли разработать шаблоны, которые работают для вас. Вот несколько указателей.
Безопасная отправка:
send()
и проверьте результат.throw
), если что-то пошло не так.Выше у вас есть учет после отправки.
Ненадежные контракты
Мне непонятно, почему средства должны быть отправлены одному из двух возможных получателей, но в любом случае есть проблема.
sends()
в одной транзакции — это красный флаг. На мой вкус, это слишком занято.Предложение: разбейте это на более мелкие функции и сосредоточьтесь на учете, а не сразу на send()
. Следите за тем, кому что причитается, как к арифметическим операциям/операциям хранения. В этом случае вам не нужно throw
, и if() {} else {}
логика должна работать нормально.
Используйте шаблон вывода, чтобы иметь дело с одной претензией и одним пользователем за раз. https://github.com/ConsenSys/smart-contract-best-practices#favor-pull-over-push-for-external-calls
Надеюсь, поможет.
В дополнение к комментариям Роба, некоторые комментарии к используемому шаблону. <some condition>
не нужно бросать так не нужно require
. Просто используйте if(<some condition>)
и полагайтесь на успех/бросок условных .send()
's.
Кроме того, the if(!<condition>)throw
можно заменить на require(<condition>)
as it throws false
(но обратите внимание на обратную условную логику).
function payMeBack() {
if(<some condition>)
require(client.send(gainedWei));
else
require(cluster.send(gainedWei));
gainedWei = 0;
client.success = 1;
}
if(require(<some condition>))
является недопустимым синтаксисом, так как require()
не возвращает логическое значение.
альпер
pay()
сначала покупаем товар, деньги будут списаны со счета клиента. В payMeBack() проверьте условие, например: успешно ли доставлен товар продавцу. Если да, то деньги, вырученные по контракту, будут выплачены продавцуseller.send(gainedWei)
. Если нет, он будет возвращен клиенту в качестве возмещенияclient.send(gainedWei)
. Надеюсь, стало немного понятнее. Таким образом, в основном payMeBack также должен решать, кто получит деньги, продавец или клиент, исходя из условий. @РобХитченс.альпер
Роб Хитченс
альпер
if
условие - это функция, и я изменю некоторые состояния, которые вернут true или false. Функция может потреблять много газа. Таким образом, может показаться, что это просто использование , посколькуthrow
возвратif/else
состояний вручную может потребовать дополнительного использования газа. @Роб ХитченсРоб Хитченс
альпер