Было рекомендовано избегать использования tx.origin.
Однако в некоторых случаях это действительно необходимо, например, в следующем случае.
Предположим, у нас есть два смарт-контракта: Sc1 и Sc2, оба из которых созданы одним и тем же владельцем . Сначала он развертывает Sc1, который поддерживает баланс токенов. Затем владелец создает еще один смарт-контракт Sc2, развертывает его и позволяет пользователям взаимодействовать с Sc2 и передавать некоторые свои токены из Sc1 в Sc2 (предположим, что у некоторых пользователей есть токены в Sc1). Но только владельцы токенов должны иметь возможность сделать это, и никто другой (даже владелец контракта ).
Как вы можете видеть ниже, я должен использовать tx.origin. Я знаю, что если владелец контракта создаст другой недействительный контракт и заставит пользователя (владельца токена) вызвать его, то он сможет уменьшить свой token_bsalance в Sc1. Ниже приведен код для вышеуказанного случая (атака исключена).
contract Sc1{
mapping (address => uint) token_balance;
mapping (address => bool) valid_caller_contracts;// keeps track
//of those contract that can call this contract
address owner;
function Sc1(){
owner = msg.sender;
}
// only owner must be able to register.
function register_valid_contract() external {
require(tx.origin==owner);
valid_caller_contracts[msg.sender] = true;
}
function decrement_token(uint val) external{
require(token_balance[tx.origin] >= val);
token_balance[tx.origin] -=val;
}
}
contract Sc2{
mapping (address => uint) token_balance2;
address owner;
function SC2(){
owner = msg.sender;
}
function register() external{
Sc1 c1=Sc1(0x22);//Let's assum the address of Sc1 after it's
//deployed is 0x22
c1.register_valid_contract();
}
// only those who have tokens in Sc1 must be able to tranfer
//tokens to Sc2.
function fetch_tokens(uint val) external{
Sc1 c1=Sc1(0x22);//Let's assum the address of Sc1 after it's
//deployed is 0x22
c1.decrement_token(val);
token_balance2[msg.sender] += val;
}
}
Вопрос : Можем ли мы в приведенном выше случае избежать использования tx.origin?
Серьезная проблема для контракта в зависимости от заключается tx.origin
в том, что ваш контракт не будет корректно работать с кошельками с мультиподписью (или с любым другим смарт-контрактом).
Решение проблемы с register_valid_contract
заключается в том, чтобы передать адрес контракта в качестве параметра, а владелец должен вызвать функцию в качестве дополнительного шага.
function register_valid_contract(address sc2) external {
require(msg.sender == owner);
valid_caller_contracts[sc2] = true;
}
Другой подход заключается в том, что SC1 использует заводские шаблоны для создания SC2 и регистрирует их сразу при создании.
Поскольку decrement_token
вы можете передать msg.sender в качестве параметра, но вы должны убедиться, что отправитель является действительным контрактом.
function decrement_token(address from, uint val) external{
require(valid_caller_contracts[msg.sender]);
require(token_balance[from] >= val);
token_balance[from] -=val;
}
В этом примере, если вы определяете доверительные отношения между SC1 и SC2, например, если SC1 создает SC2, тогда SC1 может проверить, что адрес отправителя — SC2, и верить, что параметры будут правильными.
Ай.
Исмаэль
Ай.
Исмаэль