0

I have a two smart contracts. One receives ether(ReceiveEther) and the other sends ether(SendEther). I have it set so whoever made SendEther can only send to ReceiveEther if both contract creators are the same.
However, the ReceiveEther contract can receive from anyone.
How do I make it so ReceiveEther can receive from anyone only after SendEther has successfully executed once?

pragma solidity ^0.5.11;

contract ReceiveEther {
    uint256 public count;
    address public creator= msg.sender;
        function () external payable {
            require(count < 2);
                count++;
                   } 
        function getBalance() public view returns (uint) {
            return address(this).balance;
    }

}

contract SendEther {
    address public creator= msg.sender;
    uint256 public sendcount; 
        function sendViaCall (address payable _to) public payable {
            require(msg.sender == creator);
            (bool sent, bytes memory data) = _to.call.value(msg.value)("");
            require (sent, "failed to send ether");
            require(sendcount < 1);
                 sendcount++;
    }
}

I'm sure i could create another Sending contract that looks at the counter of ReceiveEther and works only if it is >1, but I don't want to deploy an extra contract.
Thank you for any help.

EDIT
My most recent attempt is where i added another counter and a while loop.
The idea is that now there is a button the contract creator must press. While it is pressed once, only he can send to the contract. If he presses it twice, he no longer is the only one who can send to it.
It compiles without error, but I cannot send ether at any point.

pragma solidity ^0.5.11;

contract ReceiveEther {
    uint256 public clicksfromcreatorcount; 
    address public creator= msg.sender;
        function increaseifcreatorclicks() external {
            require(msg.sender == creator);
                clicksfromcreatorcount++;
        }
        function () external payable {
            require (clicksfromcreatorcount >=1);
                while (clicksfromcreatorcount==1 ) {
                    require(msg.sender == creator);
                }

        }
        function getBalance() public view returns (uint) {
            return address(this).balance;
        }
}

contract SendEtherFirst {
    address public creator= msg.sender;
        function sendViaCall (address payable _to) public payable {
            require(msg.sender == creator);
            (bool sent, bytes memory data) = _to.call.value(msg.value)("");
            require (sent, "failed to send ether");
        }
}

i get this message from the compiler

transact to SendEtherFirst.sendViaCall errored: VM error: revert.
revert  The transaction has been reverted to the initial state.
Reason provided by the contract: "failed to send ether".


Maybe the issue is with the while loop or the extra "require". I'll keep looking into it. I'm using solidity.readthedocs to understand how i should be doing things.

4
  • Dude, your require(count < 2) logic looks like it was taken from a solution to a different question of yours (and I'm pretty sure I'm the one who gave that solution). What exactly is it doing here? Seems completely inappropriate to your description and goal. PLEASE - try to understand why specific pieces of code are being used before you just "throw them into your project"! Commented May 16, 2020 at 15:51
  • you did send me it, thank you. I only want this contract to be able to receive something twice, which is why i kept it in. When posting, is it best to delete all code that isn't related to the problem?
    – rubecuber
    Commented May 16, 2020 at 15:58
  • I only want this contract to be able to receive something twice - is that still part of the requirements? Your description says something completely different (and even contradicting to a certain extent)! Commented May 16, 2020 at 16:06
  • yes it is part of the requirement. I am looking for a way for a contract that can only receive 2 transactions to have to accept one specified transaction before accepting another. In this example, the specified transaction is from "SendEther".
    – rubecuber
    Commented May 16, 2020 at 16:22

1 Answer 1

0

Superlative news, friends!
I found a way to make it work.
The key was multifold...(1)to use tx.origin rather than msg.sender. It is my understanding that these two are not the same and that tx.origin points to "the person who is running the show" and that msg.sender is just whoever is calling something.
(2) simplifying life by putting a button that only the contract creator could push. When pushed once, he could send stuff. When pushed twice, anyone could send stuff. when not pushed, no one could send anything. However! There is a friendly catch... every time a transaction goes through,an additional counter goes up one. This counter maxes out at 2, at which point no one can send any more transactions.
Having this button removed the need to create a sending contract that could only send to the payable function in another contract (as it had been before).

pragma solidity ^0.5.11;

contract ReceiveEther {
    uint256 public clicksfromcreatorcount; 
    uint256 public count;
    address public creatorino = tx.origin;

        function increaseifcreatorclicks() external {
            require (msg.sender == creatorino);
                clicksfromcreatorcount++;
        }

        function () external payable {
            require (clicksfromcreatorcount>=1);
            if (clicksfromcreatorcount ==1) {
                require (tx.origin == creatorino);
            }
            require (count<2);
            count++;
        }
}

contract SendEther {
        function sendViaCall (address payable _to) public payable {
            (bool sent, bytes memory data) = _to.call.value(msg.value)("");
            require (sent, "failed to send ether");
        }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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