Как работает этот код из стандартной реализации ERC223?

Вот фрагмент кода из стандарта ERC223-token .

function transfer(address _to, uint _value, bytes _data) {
    // Standard function transfer similar to ERC20 transfer with no _data .
    // Added due to backwards compatibility reasons .
    uint codeLength;

    assembly {
        // Retrieve the size of the code on target address, this needs assembly .
        codeLength := extcodesize(_to)
    }

    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    if(codeLength>0) {
        ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
        receiver.tokenFallback(msg.sender, _value, _data);
    }
    Transfer(msg.sender, _to, _value, _data);
}

Чего я не понимаю, так это того, как работают эти две строки:

ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
receiver.tokenFallback(msg.sender, _value, _data);

Здесь не создается новый экземпляр, но мы все еще вызываем функцию. Как мы можем вызвать функцию контракта таким образом? В ERC223RecievingContract нет конструкции, но здесь передается адрес. Что именно здесь происходит?

Ответы (3)

Любой смарт-контракт, желающий взаимодействовать с токеном ERC223, должен реализовать tokenFallback()функцию для обработки входящих переводов токенов.

Эти 2 строки вызывают эту функцию в целевой учетной записи (если это смарт-контракт), поэтому целевой смарт-контракт ДОЛЖЕН ранее реализовать функцию tokenFallback().

Как видно из примера реализации, функцию tokenFallback() можно использовать для извлечения всех данных, отправленных вызовом transfer(), и использовать их по своему усмотрению в контракте получателя:

https://github.com/Dexaran/ERC223-token-standard/blob/Recommended/Receiver_Interface.sol

ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);, этот код не создает экземпляр принимающего контракта, так как же мы вызываем его функцию? Является ли ERC223ReceiveContract конструктором?
Когда вы делаете ContractX x = ContractX(адрес контракта), вы создаете экземпляр существующего контракта по указанному адресу. Если вы знаете его функции, вы можете вызывать их из другого контракта.

Это то же самое, что и резервные функции для эфира.

из документов:

Токены ERC223 должны быть отправлены путем вызова функции передачи по контракту токена без разницы, является ли получатель контрактом или адресом кошелька. Если получателем является кошелек, передача токена ERC223 будет такой же, как и передача ERC20. Если получатель является контрактом с токеном ERC223, он попытается вызвать функцию tokenFallback для контракта с получателем. Если в контракте-получателе нет функции tokenFallback, транзакция контракта-получателя завершится ошибкой. Функция tokenFallback является аналогом резервной функции для транзакций эфира. Его можно использовать для обработки входящих транзакций.

Это может быть не так очевидно, но это влечет за собой следующее:

Токены ERC223 следует использовать при отправке перевода. Если получателем является кошелек, то проблем не будет. Если получателем является контракт, то передача попытается вызвать функцию tokenFallback. Если tokenFallback отсутствует, транзакция завершится ошибкой.

Однако вы можете реализовать tokenFallback для обработки входящих транзакций с токенами в ваш контракт. В следующем примере будут отклонены все входящие транзакции с токенами, кроме транзакций, выпущенных краудсейлом, которые будут добавлены обратно к доступному балансу краудсейла.

  function tokenFallback(address, uint _value, bytes)
      isToken
      public {
      _available = _available.add(_value);
  }

Как ранее указывал Pabloruiz55, его также можно использовать для получения информации о транзакции: msg.sender, msg.value и msg.data, вы также можете отправить эти значения, если вы решите реализовать функцию tokenFallback, поскольку они передаются как параметры функции. .

Можете ли вы рассказать мне, как работает этот код: ERC223ReceiveContract Receiver = ERC223ReceiveContract(_to);
Если получатель (_to) является контрактом, вы создадите экземпляр уже определенного ERC223ReceiveContract по этому адресу, с которого вы затем сможете вызвать tokenFallback. ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);определение переменной 'тип' (здесь экземпляр контракта --- мы вызываем переменную приемник --- мы вызываем контракт с параметром _to
Извините, я был неправ. Вы не заключаете новый контракт на адрес _to. Вы только указываете, что контракт можно найти там, если он реализован. Чтобы узнать больше по этой теме, посмотрите следующее видео на YouTube: youtube.com/watch?v=l_E5F5qnbtk
@Kyriediculous. Спасибо, но как Solidity может восстановить баланс токенов? Пожалуйста, смотрите мой ответ ниже...

Спасибо Kyriediculous за объяснение полиморфизма в Уроке 17 Полиморфизм https://www.youtube.com/watch?v=l_E5F5qnbtk

   ContractReceiver receiver = ContractReceiver(_to);

мы только предполагаем, что по адресу _to есть контракт (или реализация интерфейса) с именем ContractReceiver

    receiver.tokenFallback(msg.sender, _value, _data);

и теперь мы предполагаем, что такой контракт в _to имеет функцию tokenFallback

но если такой функции или такого контракта по такому адресу не существует, мы получаем отказ... тогда что?

Я нашел это здесь: Разбивка EIP: Стандарт токена ERC 223 https://www.youtube.com/watch?v=GS62VNyPVHs Также см. «Атомные свопы Ethereum Cross Chain» для атомарных транзакций https://medium.com/@DontPanicBurns /ethereum-cross-chain-atomic-swaps-5a91adca4f43

В Solidity транзакции называются атомарными, что означает, что либо вся транзакция завершается успешно, либо все вместе терпят неудачу. Таким образом, даже если одна строка (приемник.tokenFallback()) в функции завершается с ошибкой, вся функция вместе с ошибкой. Затем балансы будут восстановлены до исходных значений.

Решено для переноса токенов ERC223 в контракт, несовместимый с ошибкой/сбоем