3

I'm using testrpc, and truffle. I created a simple token as seen in many tutorials which shall be used to buy or enable certain actions when clicking a button on an UI.

contract MyToken {
    mapping (address => uint) balanceOf;

    event CoinTransfer(address indexed _from, address indexed _to, uint256 _value);

    function MyToken() {
        balanceOf[msg.sender] = 21000000;
    }

    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        if (balanceOf[msg.sender] < amount) return false;
        balanceOf[msg.sender] -= amount;
        balanceOf[receiver] += amount;
        CoinTransfer(msg.sender, receiver, amount);
        return true;
    }

    function getBalance(address addr) returns(uint) {
        return balanceOf[addr];
    }
}

So far so good.

The UI has a button "buy 10 MyToken" which is working as I have implemented a function in app.js with the deployed JS object of that contract.

function buyMyToken(amount) {
  var mytoken = MyToken.deployed();

  showStatus("Initiating transaction... (please wait)");

  mytoken.sendCoin(myaccount, amount, {from: spender}).then(function() {
    showStatus("Transaction complete!");
    refreshBalance();
  }).catch(function(e) {
    console.log(e);
    showStatus("Error sending coin; see log.", true);
  });
}; 

Now I want to create another contract which will allow the user to buy a licence,service or enable some action for instance,when clicking another button.Which in that case shall enable a picture permanently on the UI when being bought once with that token. So that second button should enable a gimmick permanently and the cost is for instance 5 of my own created token --> "enable gimmick (5 MyToken)"

For that contract inheritance is needed right? Because the second contract has to check if the user has already bought some of the tokens with the first contract, which would allow him to buy some license,service or enable some action with the second contract. So what do I need for that second contract and how can I build and use it in connection with the first contract?

Could second contract be like this or what else do I need?I know I need for instance the getBalance function from the first contract right?But how and where I put it?

contract PermService {
  address vendor;

  event ServiceTransfer(address _from, address _to, uint _amount)

  function PermService() {
  vendor = msg.sender;


  }

  function buyPermService() returns (bool success) {
  if...
  ...
  ServiceTransfer(msg.sender, receiver, amount);
  return true;
  }
}

Does that even make any sense?

Can not really find good tutorials for subcurrencies and how to use them with other contracts. I'm also a noob and not a pro coder.

And can I do simulate that with truffle console?

Help is much appreciated. Thanks in adavance.

3 Answers 3

2

Ok this is what I've done so far. And yeah it's not contract inheritance what I was looking for, it's contracts interacting with each other.

contract MyToken {
    mapping (address => uint) balanceOf;

    event CoinTransfer(address indexed _from, address indexed _to, uint256 _value);

    function MyToken() {
        balanceOf[msg.sender] = 21000000;
    }

    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        if (balanceOf[msg.sender] < amount) return false;
        balanceOf[msg.sender] -= amount;
        balanceOf[receiver] += amount;
        CoinTransfer(msg.sender, receiver, amount);
        return true;
    }

    function transfer(address from, address to, uint amount) returns(bool sufficient) {
        if (balanceOf[from] < amount) return false;
        balanceOf[from] -= amount;
        balanceOf[to] += amount;
        CoinTransfer(from, to, amount);
        return true;
    }

    function getBalance(address addr) returns(uint) {
        return balanceOf[addr];
    }
}

contract PermService {
    mapping (address => bool) customerPaid;
    address vendor;

    function PermService() {
        vendor = msg.sender;
    }

    function buy(address tokenContractAddress) returns (bool success) {
        if (customerPaid[msg.sender]) {
            // permanent: the customer already bought the service!
            return true;
        }
        MyToken mt = MyToken(tokenContractAddress);
        if (mt.getBalance(msg.sender) < 5) {
            throw;
            return false;
        }
        mt.transfer(msg.sender, vendor, 5);
        customerPaid[msg.sender] = true;
        return true;
    }
}

contract OnetimeService {
    address vendor;

    function OnetimeService() {
        vendor = msg.sender;
    }

    function buy(address tokenContractAddress) returns (bool success) {
        MyToken mt = MyToken(tokenContractAddress);
        if (mt.getBalance(msg.sender) < 2) {
            return false;
        }
        mt.sendCoin(vendor, 2);

        return true;
    }

}

contract TimeLimitedService {
     ....
     //block.timestamp an option??

}

As you can see I created 4 contracts in one file.4 buttons in the UI and for each I created a contract. The first contract creates the token which can be used by customers to buy services from the issuer of that token.As I mentioned in my opening comment this is already working. Customer hits the button "Buy 10 Mytoken" and done.

The second contract shall enable a permanent service which only needs to be bought once. So far this is mostly working.When I haven't bought any of MyToken and hit the button "enable gimmick" it returns "Error buying Service, see log".This is correct. And when I buy some of MyToken first and then hit the "enable gimmick", a gimmick pops up and the balance gets reduced by 5 MyToken.When I hit the "enable gimmick" button again it doesn't withdraw any tokens because I already bought before. However there are still transactions happening.Not the perfect solution I'm having so far. I'm sure there are much better ways to code that.Improvement and simplifications are appreciated.

And any idea how I can write a smart contract with some kind of time limited service/action? I read that block.timestamp could be an option.The idea is that when a button gets hit in the UI, from that moment on, or when this transaction got included in a block, the color of the background may change for 30 seconds or something like that.Some help here is appreciated as well.

1

You might not be looking for contract inheritance here.

When contract B inherits from contract A, it's (generally) a complete copy of A as well as whatever B adds. So if you create one token contract, and then create a second contract that inherits from the token contract, you'll actually have two kinds of tokens!

This, however, might not be a bad thing. If selling this service is intrinsically linked to the token, it might make more sense to just have one contract that both keeps track of tokens and sells services. There's a number of reasons you might not want to do this, though. (Complexity, difficulty in upgrading, etc...)

So how do you do it with two contracts? Essentially, you'll need to give the seller contract the right to alter the balance of the token contract. Here's a snippet for a simple way to do that.

modifer onlyseller() {
    if(msg.sender != seller) throw;
    _;
}

function takeTokens(address buyer, uint amount) onlyseller {
    if(balanceOf[buyer] < amount) throw;
    balanceOf[buyer] -= amount;
    balanceOf[seller] += amount;
    CoinTransfer(msg.sender, receiver, amount);
}

This will create a function in the token contract that only seller can access. Any other call will throw. (In this case, that's probably a good thing. throw (generally) undoes the whole transaction.)

Then, in the seller contract, you can use this function.

// in the constructor.
mytoken = MyToken(tokenContractAddress);

// in buyPermService(). I assume msg.sender is the buyer.
// you'll need to mark balanceOf as public for this to work.
if(mytoken.balanceOf(msg.sender) > priceOfService) { 
    mytoken.takeTokens(msg.sender, priceOfService);
    // Actually provide the service here.
}  

However, this is not the best method.

The ERC20 token standard (a great resource on tokens in general) specifies a method called transferFrom() and recommends a method called approve(). One address can use approve() to permit another address to withdraw some tokens through transferFrom(). With this, it'd be simple to create a seller contract. The buyer gives the seller the right to withdraw so many tokens through approve(), and the seller uses transferFrom() to actually get those tokens. This is indeed much better, because you (or anyone else) can add new sellers to the system. It'd be well worth your time to implement this.

1
  • Thanks for your answer.Will have to go through your recommandations later.I played a bit around with my own version.Will post it here as well and maybe you could have a look at it for some improvements.
    – Viktor
    Dec 9, 2016 at 22:37
1

Agree with Mathew about ERC20 versus roll-your-own token. I'm not sure time-limited is really what you want for a oneTimeService. Here's another way to look a timing in any case:

 function f(uint durationInMinutes) {
    uint deadline = now + durationInMinutes * 1 minutes;
 } // unit time in seconds +/- 900 seconds

Not sure you need a separate contract for the oneTimeService ... Not sure timing is the way to go. Consider making it explicitly one-time if that's the intent:

contract C {

mapping(address => bool) alreadyDone;

function oneTime(address user) returns(bool success) {
    if(alreadyDone[user]) throw;
    // do something
    alreadyDone[user]=true;
}

}

If this is in service to the UI, then you probably want to use the one-time pattern and an event emitter or mined transaction for confirmation that something really happened.

add:

event LogItHappened(address user); // initialize it

//do something
LogItHappened(user); // UI can watch for this with an event listener. 

Your Answer

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

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