Let's say that you have this contract that can only be updated from updater
's address:
contract StringStore {
string public myString;
address public updater; // This is a contract's address
function StringStore(address _updater) {
updater = _updater;
}
function setString(string newString) {
if (updater != msg.sender) throw;
myString = newString;
}
}
Let now say that the updater
's address is this contract that notifies whichever listener of required calls:
contract HoldOff {
address public owner;
event LogRequest(
address requester,
address target,
bytes msgData);
function HoldOff() {
owner = msg.sender;
}
function requestCall(address target, bytes msgData)
returns (bytes32 key) {
LogRequest(msg.sender, target, msgData);
}
function doCall(address target, bytes msgData)
returns (bool) {
if (owner != msg.sender) throw;
return target.call(msgData);
}
}
And finally, to make a test in Truffle, which uses EtherPudding:
contract('HoldOff', function(accounts) {
var owner = accounts[0];
var requester = accounts[1];
it("should be able to have delayed action", function() {
var holdOff = HoldOff.deployed();
var stringStore = StringStore.deployed();
var msgData;
return stringStore.myString()
.then(function (myString) {
assert.equal(myString, "", "should be an empty string to start with");
// Requester collects necessary data
// We get the call data. With EtherPudding we need to do .contract, otherwise, it is a straight .getData()
msgData = stringStore.contract.setString
.getData("Hello World", { from: requester });
// We only want events coming in new blocks
var blockNumber = web3.eth.blockNumber;
// Requester requests...
holdOff.requestCall(stringStore.address, msgData, { from: requester });
// See https://gist.github.com/xavierlepretre/afab5a6ca65e0c52eaf902b50b807401
// Let's wait for the event to fire, in effect that the block was mined.
return getEventsPromise(holdOff.LogRequest(
{},
{ from: web3.eth.blockNumber }));
})
.then(function (events) {
// In effect, there was just one event.
return holdOff.doCall(
events[0].args.target,
events[0].args.msgData,
{ from: owner });
})
.then(function (tx) {
// See https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6
return web3.eth.getTransactionReceiptMined(tx);
})
.then(function (receipt) {
// Let's make sure it was updated.
return stringStore.myString();
})
.then(function (myString) {
console.log(myString);
assert.equal(myString, "Hello World", "should have been updated");
});
});
});