Как создать функцию Payable, которая принимает только токен клиента?

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

Я пытаюсь создать контракт с функцией Payable, которая принимает в качестве оплаты только определенный токен, а не ETH. Я владею как контрактом на токен, так и этим контрактом, который специально создан для приема оплаты за этот конкретный токен.

Это вообще возможно? Я нашел это как возможное решение:

Источник: как создать краудсейл, который принимает только определенный токен erc20?

contract Crowdsale {

        address owner;  
        mapping(address => uint256) balances;
        function Crowdsale(){
            owner = msg.sender;
        }

        function acceptOnlyMyToken(address _yourTokenAddress, uint256 amount){
            address user = msg.sender;
            YourToken token = YourToken(_yourTokenAddress);

            //get the user's balance
            uint256 userBalance = token.balanceOf(user);
            //check user's balance
            if(userBalance >= amount){      
                token.transferFrom(user, owner, amount);        

            }

        }

    }

Безопасно ли предположить следующее с приведенным выше кодом?

  1. Замена YourToken token = YourToken(_yourTokenAddress);на YourToken token = YourToken(address(0xABCD...));«0xABCD», являющаяся адресом моего токена, который находится в отдельном контракте, должна работать.
  2. Указание require(msg.value == 100под acceptOnlyMyToken(...)функцией позволит мне установить конкретную требуемую сумму платежа.

Кроме того, я не вижу, чтобы эта функция называлась «оплачиваемой», имеет ли это значение? Причина в том, что я хочу передать переменные как часть функции, чтобы выполнить работу XYZ как часть логики контракта, за которую я получаю оплату в виде определенного количества этого токена.

Есть предположения?

Ответы (1)

Вы не используете payableдля непротокольного типа передачи. ERC20 не является «протоколом», потому что он определен в контракте.

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

uint myTokenBalance = IERC20(<tokenAddress>).balanceOf(address(this));

Вы ищете шаблон "одобрить и передать от". Это выглядит так:

  1. Пользователь разрешает вашему контракту получать средства из баланса токенов пользователя.

  2. Затем пользователь вызывает функцию в вашем контракте, которая пытается получить токены.

Шаг 2 выглядит так:

function sendMe100() external {
  IERC20(<tokenAddress>).transferFrom(msg.sender, address(this), 100);
  // success
}

Вышеизложенное предполагает , что пользователь авторизовал передачу, сначала вызвав approveфункцию в контракте ERC20 (шаг 1), но обычно это внешняя проблема, которая не имеет отношения к вашему контракту.

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