Приложение смарт-контракта, которое я пишу, следует тому, что я считаю хорошей практикой — оно отделено, так что контракт контроллера вызывает логический контракт, который вызывает контракт хранилища. Так Contract A
звонки Contract B
звонки Contract C
.
Однако мне интересно, является ли из-за безопасности такая развязка хорошей идеей для смарт-контрактов. Это потому, что мне нужен onlyOwner
модификатор, чтобы связать, кто вызывает мои функции (как описано здесь: https://github.com/ethereum/wiki/wiki/Solidity-Features ). На мой взгляд, было бы здорово, если бы я мог сделать что-то вроде этого:
import "Owned.sol";
contract A is Owned {
B private b;
function A(address B) {
b = B(b);
}
function myInterface() public onlyOwner {
a.doStuff({from: msg.sender});
}
}
contract B is Owned {
C private c;
function B(address c) {
c = C(c);
}
function doStuff() public onlyOwner {
c.store(42,{from: msg.sender});
}
}
contract C is Owned {
int private theAnswer;
function store(int value) public onlyOwner {
theAnswer = value
}
}
Однако я считаю, что не могу отправить msg.sender
таким образом. Contract A
Следовательно , было бы лучше объединить Contract B
в Contract C
единый монолитный контракт, где msg.sender
он действителен?
В комментариях к исходному сообщению вы указали, что развертывание крупного монолитного контракта может завершиться неудачей из-за достижения лимита блочного газа. Децентрализованное приложение, которое нельзя развернуть, не может быть лучше. :)
Что касается решений: возможно, распространяется Owned
на Authable
:
mapping (address => bool) public authorised
modifier onlyAuthed {...}
function authAdd (address _addr) public onlyOwner {...}
function authRem (address _addr) public onlyOwner {...}
... а затем использовать Authed
+ onlyAuthed
вместо Owned
+ onlyOwner
в производных приложениях?..
Затем вы можете развернуть части независимо друг от друга. Когда есть «полная цепочка», которую можно связать (например A->B->C[several]
, вы можете звонить C.authAdd(<address-of-B>)
из своей owner
учетной записи.
Это немного утомительно, но относительно легко автоматизируется. Кроме того, вам не нужно беспокоиться о порядке развертывания или о том, что некоторые децентрализованные приложения не развернутся.
Схема может быть изменена в соответствии с конкретными потребностями.
В качестве альтернативы вы можете использовать Ownable от Zeppelin и его transfer()
функцию.
Это будет работать нормально, если:
РЕДАКТИРОВАТЬ:
Опять же, вы можете перейти b = B(b)
от конструктора к отдельной функции (например function createChildren(...) public onlyOwner onlyOnce {...}
) и добавить способ распространения запроса на уже созданные дочерние элементы (например function nagForGrandChildren(...) public onlyOwner {...}
). Но проблема остается: при nFGC()
достижении лимита газа в блоке вызов функции придется повторить — инициировать из исходной внешней owner
учетной записи A
.
Так или иначе, вам нужно будет предвидеть, что какая-то часть вашей цепочки не сможет развернуться. Выбор здесь между «что-то в будущем» или «что-то среднее».
Тьяден Хесс
светлячок
Тьяден Хесс
msg.sender
его в конструкторе B для установки владельца. Затем сделайте то же самое, создав C из конструктора B.светлячок
Тьяден Хесс
светлячок
new
s. Но теперь я знаю немного больше, так что я проведу повторное расследование.Тьяден Хесс
светлячок
new
подход, и действительно, у меня закончился газ. Для этого требуется около 7 миллионов газа. Следовательно, мне нужно передавать адреса. К сожалению, выше я не понял, что я не могу передать адрес B для C, чтобы C мог сделать B своим владельцем, поскольку B сначала нужен адрес C. Существуют способы «передачи права собственности» обратно В, но все они довольно запутаны. Это возвращает меня к заголовку моего первоначального поста: не лучше ли мне избежать всей этой сложности, просто объединив все необходимые функции в один контракт? Я надеюсь, что не должны быть лучшие способы...