I have a simple function in contract x that subtracts a value from contract y, is it possible to have contract x send a message to the user of contract y and set a condition that untill user confirms the activity the contract does not execute?

Thank You


You can make this workflow, but if it's all on-chain then you'll have to build all the parts, and each step in the workflow will require a transaction, so one for "Request action" and another for "Confirm action".

Also contracts can't send email or anything, so sending a message to the user of contract y means writing something to the event log or adding a message to a queue, then hoping the receiver is reading it. (You may of course have some off-chain service listening for this event and sending email or whatever.)

If you have to do the notification off-chain anyhow, one interesting pattern might be for the initiator to sign some data requesting the action, then send it not to the contract but directly to the user who is supposed to confirm. That user then sends a single transaction to the blockchain, which checks msg.sender to validate the confirmer, then checks the signed data with ecrecover to validate the action of the initiator.


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(
            { 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) {
        assert.equal(myString, "Hello World", "should have been updated");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.