На этой неделе поговорим о функциях в стандарте и некоторых моментах его использования.
1. transfer():
Функция перевода ERC-6909 ведет себя так же, как и трансфер ERC-20, за исключением того, что она применяется к конкретному идентификатору токена. Функция принимает адрес получателя, id токена и сумму для перевода в качестве входных параметров и обновляет балансы с помощью связки balanceOf. Как и в функции перевода ERC-20, необходимо вернуть true, если транзакция выполнена успешно:
function transfer(address receiver, uint256 id, uint256 amount) public returns (bool) {
if (balanceOf[msg.sender][id] < amount) revert InsufficientBalance(msg.sender, id);
balanceOf[msg.sender][id] -= amount;
balanceOf[receiver][id] += amount;
emit Transfer(msg.sender, msg.sender, receiver, id, amount);
return true;
}2. transferFrom():
Функция transferFrom в ERC-6909 отличается от функции ERC-20 тем, что требует идентификатор токена. Кроме того, она проверяет наличие одобрения оператора в дополнение к разрешению.
Сначала функция проверяет, если (sender != msg.sender && !isOperator[sender][msg.sender]), гарантируя, что вызывающая сторона (msg.sender) является либо:
- Владелецем (отправителем), либо
- Одобренным оператором (isOperator[sender][msg.sender] == true).
Если отправитель msg.sender не является таковыми, то функция проверяет, достаточно ли у вызывающего абонента средств для перевода. Если резерв существует, но не установлен в неограниченное значение (type(uint256).max), то переведенная сумма вычитается из резерва.
Кроме того, в стандарте указано, что функция НЕ ДОЛЖНА вычитать сумму из резерва вызывающего абонента по идентификатору токена, если вызывающий абонент является оператором или отправителем.
function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public returns (bool) {
if (sender != msg.sender && !isOperator[sender][msg.sender]) {
uint256 senderAllowance = allowance[sender][msg.sender][id];
if (senderAllowance < amount) revert InsufficientPermission();
if (senderAllowance != type(uint256).max) {
allowance[sender][msg.sender][id] = senderAllowance - amount;
}
}
if (balanceOf[sender][id] < amount) revert InsufficientBalance();
balanceOf[sender][id] -= amount;
balanceOf[receiver][id] += amount;
emit Transfer(msg.sender, sender, receiver, id, amount);
return true;
}3. approve():
Функция approve позволяет вызывающей стороне (msg.sender) предоставить определенное разрешение к ID спендеру. При этом обновляется маппинг, чтобы отразить новое состояние, и порождается событие Approval:
function approve(address spender, uint256 id, uint256 amount) public returns (bool) {
allowance[msg.sender][spender][id] = amount;
emit Approval(msg.sender, spender, id, amount);
return true;
}4. setOperator():
Функция setOperator позволяет вызывающей стороне (msg.sender) предоставить или отозвать разрешения оператора для определенного адреса (spender) от своего имени, установив параметр approved в true или false. Функция соответствующим образом обновляет отображение isOperator и порождает событие OperatorSet, чтобы уведомить внешних слушателей об изменении.
function setOperator(address spender, bool approved) public returns (bool) {
isOperator[msg.sender][spender] = approved;
emit OperatorSet(msg.sender, spender, approved);
return true;
}5. Events:
В стандарте предусмотрены три события для порождения в ключевых функциях:
event Transfer(address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount);
event OperatorSet(address indexed owner, address indexed spender, bool approved);
event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
#eip6909