Перенести все msg.sender.balance в контракт, не требуя от пользователя ввода msg.value?

Есть ли способ слить весь пользовательский баланс на контракт или внешний оплачиваемый адрес, не требуя от пользователя ввода msg.value?

Самая интуитивно понятная версия, которая у меня была, выглядит примерно так на Solidity 0.5.0:

address(this).transfer(msg.sender.balance)

Однако похоже, что контрактный адрес по своей сути не подлежит оплате, поэтому я попытался сначала преобразовать его в оплачиваемый адрес:

address payable payableContract = address(uint160(address(this)))

Но, похоже, это тоже не работает. Кто-то предложил мне заглянуть в Contract Factory, который может решить проблему. Что было бы лучшим способом обойти это, чтобы добиться того же результата?

Контракт не может принудительно забрать эфир пользователя.
@smarx Есть ли у пользователя способ предварительно авторизовать транзакцию?
Единственный способ передачи баланса внешней учетной записи — это если эта учетная запись отправляет транзакцию, которая переводит этот эфир.
@smarx Нравится договор условного депонирования?
Вы говорите о балансе Eth или балансе ERC20? Я покажу вам, что вы _можете_делать, но сосредоточение внимания на одном или другом упростит задачу.
@ RobHitchens-B9lab Идеально для обоих, но передача эфира важнее того, что я сейчас создаю.

Ответы (1)

Вам нужно изменить ход вещей, иначе это никогда не будет иметь смысла.

Невозможно закодировать контракт на перевод средств с пользовательского кошелька. Не все, не некоторые, не любые.

address(this).transfer(msg.sender.balance)

Это означает, что пункт назначения ( to) есть address(this), а сумма равна msg.senderбалансу . from: addressнеявно , address(this) потому что ничего другого невозможно . Поэтому fromне упоминается в синтаксисе.

На самом деле вы хотите, чтобы пользователь подписал транзакцию, которая отправляет его деньги на ваш контракт. Я не знаю, почему это должен быть их полный баланс, и это звучит для меня как еще одна дизайнерская ошибка, но вот как бы вы это сделали.

Это передняя забота. Опять же, для акцента, потому что только пользователь может разрешить перевод собственных средств. На стороне контракта все, что вы можете сделать, это получить его, подтвердить транзакцию и, возможно, отклонить ее, если что-то не так.

function depositFunds() public payable {
  // carry on
  // msg.value and msg.sender inform about who and how much
}

На внешнем интерфейсе вы должны использовать Web3 или аналогичную библиотеку, чтобы помочь пользователю сформировать действительную транзакцию с amount: as much as possible, to: your contract, {gas: amount, gasPrice: bid}.

Пользователь должен платить за газ, и это уменьшит количество средств, доступных для отправки на ваш контракт. Вы должны принять это во внимание. Ваш интерфейс должен будет выяснить:

  • смета газа на сделку
  • gasPrice (стоимость потребленного эфира = оценка газа * gasPrice)
  • Средства, доступные для отправки (баланс пользователя - израсходованная стоимость), в результате чего у пользователя остается ровно 0 остатка на балансе.

Если браузер (или сервер) выполняет вычисления, то пользователю будет предоставлена ​​возможность подписать транзакцию, отправив сумму x и предложив y за газ, с оценкой газа z, в результате чего у них останется окончательный баланс 0.

Мне непонятно, почему кто-то соглашается на такие условия.

Надеюсь, поможет.

Привет, Роб, очень ценю твои усилия и время, чтобы ответить на этот вопрос. Мне нравится ваша благотворительность и подробности в ответе. Мы хотим создать что-то, что по существу требует от Алисы предварительной авторизации ожидающей транзакции, которая отправит весь ее баланс Бобу в будущем. Таким образом, одна из самых больших проблем проектирования заключается в том, что мы не знаем, каким будет этот будущий msg.balance при соблюдении определенных условий.
Самый простой подход — попросить Алису поместить часть средств в контракт, который будет передан только Бобу. Боб сможет увидеть, что средства заблокированы для него. Многое зависит от реального варианта использования, который вы имеете в виду.
Существуют ли другие подходы, которые могут творчески обойти это?
Как и просили, ничего очевидного, но то, как вы описываете «отправить полный баланс», мне не кажется разумным. Я думаю, вы можете навязывать скрытые предположения в прецедент, к которому следует подходить по-другому. Если бы вы были моим клиентом, я бы спросил вас, что Алисе и Бобу нужно знать и что делать, и продолжал бы спрашивать, пока вы не объясните это, не сказав мне, как, по вашему мнению, это должно быть закодировано.
Я мог бы сказать ELIF, объяснить это так, как будто я конечный пользователь, объяснить это так, чтобы моя мама могла это понять.
Ах. Один из способов решить эту проблему — контракт с кошельком (не EOA). Различные стороны в договоре имеют разные привилегии. Обычный владелец может быть единственным подписантом, который может делать обычные вещи. Кворум попечителей мог бы, возможно, принять решение по такому решению, как конфискация. Это не контракт, который пытается сделать с кошельком невозможное. Это кошелек, реализованный в виде контракта. Другой способ решить эту проблему - использовать кодирование стирания в закрытом ключе владельца, чтобы что-то вроде 2/3 фрагментов могло его собрать. Спасибо, что приняли мой ответ, если вы найдете его полезным.
Как мы используем кошелек, который реализован как контакт? Мне нравятся ваши предложения, кстати
Нас накажут за то, что мы слишком болтливы. Это сделало бы хороший новый вопрос. По сути, вы заключаете контракт, который передает команды, а владелец контракта отправляет его. Вы можете изучить мультиподписные кошельки для некоторых идей. У него потенциально может быть «владелец» и набор делегатов, которые могут проголосовать за захват контроля через transferOwnership(). Деталей, конечно, нужно продумать много, поэтому все оговаривается заранее. Владелец должен время от времени менять делегатов.
Спасибо за все советы, которые вы предоставили до сих пор. В течение последнего часа искал кошельки с мультиподписью. Сообществу Ethereum определенно нужно больше таких людей, как вы. Ты мужчина, Роб!