Ich stehe wiederholt vor diesem Problem mit dem Code für die Strukturierung von Verträgen:
contract Allower {
Allowed allowed;
function doSth() onlyallowed;
modifier onlyallowed {
if (msg.sender != address(allowed))
throw;
_
}
}
contract Allowed {
Allower allower;
function doSthOnAllower() {
allower.doSth();
}
}
Um durchzusetzen, dass nur eine bestimmte Instanz von Allowed
ausgeführt Allower.doSth
wird, müssen die Verträge gegenseitige Referenzen beibehalten (vorausgesetzt, wir mögen die 1-1-Beziehung, möchten diese Verträge aber dennoch getrennt halten). Um nun beide Verträge bereitzustellen und zum Laufen zu bringen, müssen wir mehr oder weniger hinzufügen:
contract Allower {
// snip...
function Allower(Allowed _allowed) {
allowed = _allowed;
allowed.setAllower(this);
}
}
contract Allowed {
// snip...
function setAllower(Allower _allower) allowernotset {
allower = _allower;
}
}
Gibt es ein Muster, das es ermöglichen würde, die Notwendigkeit von zu umgehen setAllower
? Es scheint nur ein Anti-Pattern zu sein, wenn sich solche "Set"-Methoden ausbreiten.
Laut hier :
Beachten Sie, dass es uns die neue Vertragsadresse gegeben hat. Woher kommt diese Adresse? Es ist der sha3-Hash der RLP-Kodierung der Liste [Adresse des Absenders, Sequenznummer des Absenders].
Wenn Sie im Voraus wissen, zu welcher TX-Nonce Sie bereitstellen werden, Allower
und Sie diese RLP-Berechnung selbst durchführen können, können Sie die Adresse berechnen, die Sie an den Konstrukteur Ihres Allowed
Vertrags weitergeben. Und umgekehrt.
Lassen Sie uns dieses Python-Skript in Javascript reproduzieren :
#!/usr/bin/nodejs var ethJsUtil = require('ethereumjs-util'); var account = "0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0"; console.log("nonce0=" + ethJsUtil.bufferToHex(ethJsUtil.generateAddress(account, 0))); console.log("nonce1=" + ethJsUtil.bufferToHex(ethJsUtil.generateAddress(account, 1))); console.log("nonce2=" + ethJsUtil.bufferToHex(ethJsUtil.generateAddress(account, 2))); console.log("nonce3=" + ethJsUtil.bufferToHex(ethJsUtil.generateAddress(account, 3)));
Mein Interesse stieg, ich habe hier auch ein kleines Truffle-Projekt erstellt, wo ich für die Bereitstellung Folgendes mache:
module.exports = Funktion (Bereitsteller) { // Sie müssen npm install -g ethereumjs-util ausführen var ethJsUtil = require('/usr/lib/node_modules/ethereumjs-util/'); var currentNonce = web3.eth.getTransactionCount(web3.eth.accounts[0]); var futureLeftNonce = aktuelleNonce; var futureLeftAddress = ethJsUtil.bufferToHex(ethJsUtil.generateAddress( web3.eth.accounts[0], futureLeftNonce)); var futureRightNonce = futureLeftNonce + 1; var futureRightAddress = ethJsUtil.bufferToHex(ethJsUtil.generateAddress( web3.eth.accounts[0], futureRightNonce)); deployer.deploy (links, futureRightAddress); deployer.deploy (Rechts, futureLeftAddress); };
Ich bin mir nicht sicher, inwieweit es das Problem beheben würde, aber man kann erwägen, die "1-1-Beziehung" in einen separaten Vertrag aufzunehmen, der vor beiden Allower
und eingesetzt wird Allowed
.
contract Handcuffs {
address left;
address right;
// set() must be called by both handcuffed contracts
function set() {
if (left == 0x0)
left = msg.sender;
else if (right == 0x0)
right = msg.sender;
else
throw;
}
// once handcuffed, get() always returns the other contract
function get() constant returns (address partner) {
if (msg.sender == left && right != 0)
return right;
else if (msg.sender == right && left != 0)
return left;
else
throw;
}
}
contract Allower {
Handcuffs allowed;
function Allower(Handcuffs _allowed) {
allowed = _allowed;
allowed.set();
}
function doSth() onlyallowed;
modifier onlyallowed {
if (msg.sender != allowed.get())
throw;
_
}
}
contract Allowed {
Handcuffs allower;
function Allowed (Handcuffs _allower) {
allower = _allower;
allower.set();
}
function doSthOnAllower() {
var allowerContract = Allower(allower.get());
allowerContract.doSth();
}
}
Eine Alternative dazu wäre, den Deployer-Aufruf explizit setzen zu lassen und somit Allower
von Allowed
jeglicher Verantwortung zu befreien:
contract Handcuffs {
// snip...
function set(address _left, address _right) onlydeployer onlyonce {
left = _left;
right = _right;
}
// snip...
}