I am working on a smart contract in which requirement is if someone purchases tokens by ether and after the purchase if he/she wants to return the token and get ether balance back. As in my requirement, I need to calculate the price of ether at run time after his/her purchase. So when I do code like this, here 1000000000000000000 is hardcoded but in my case, it calculated on runtime to return ether balance to the customer.

function sell(uint256 amount) payable public  {
   msg.sender.transfer(1000000000000000000);        /// sends ether to the seller.  

This throw following error

transact to Scalifyt5Token.sell errored: VM error: revert.
revert  The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value.  Debug the transaction to get more information. 

If I do in this way enter ether amount from input in ether that is working fine. but that is not my requirement as I need to calculate wei value at runtime.

function sell(uint256 amount) payable public  {
   msg.sender.transfer(msg.value);        /// sends ether to the seller. 

Any help will be appreciated.

Thanks in advance.

1 Answer 1


If the function is payable the buyer can send ether directly. I think rather than "sell", the name of the function should by buy (after all is the user who execute the function and he/she will be buying)

Assuming that:

mult_dec is a constant equal to 10**decimals where decimals = 18; The price per token is price (for instance 100000000000000000 wei = 1ETH)

function buyTokens() public payable{
    uint numberofTokens = msg.value.mul(mult_dec).div(price);        
    balance[msg.sender] = balance[msg.sender].add(numberofTokens); 

Note that if you execute this form mist, it will show fields to put the amount of ether.

For selling the token back to your contract:

function sellTokens(uint amountTokens) public {
    balance[msg.sender] = balance[msg.sender].sub(amountTokens);
    uint amountEther = amountTokens.mul(price).div(mult_dec);

You can find more information in the ethereum oficial website in example of a token

Hope this helps.


I implemented a simple contract to buy and sell using the functions above and it works.

pragma solidity ^0.4.21;
library SafeMath {
    function add(uint a, uint b) internal pure returns (uint c) {
        c = a + b;
        require(c >= a);
    function sub(uint a, uint b) internal pure returns (uint c) {
        require(b <= a);
        c = a - b;
    function mul(uint a, uint b) internal pure returns (uint c) {
        c = a * b;
        require(a == 0 || c / a == b);
    function div(uint a, uint b) internal pure returns (uint c) {
        require(b > 0);
        c = a / b;

contract MyContract{
    using SafeMath for uint256;

    uint public price;
    uint public mult_dec;
    mapping(address => uint) public balances;

    function MyContract() public {
        price = 1000000000000000000;
        mult_dec = 10**18;

    function sellTokens(uint256 amountTokens) public {
        balances[msg.sender] = balances[msg.sender].sub(amountTokens);
        uint amountEther = amountTokens.mul(price).div(mult_dec);

    function buyTokens() public payable{
        uint numberofTokens = msg.value.mul(mult_dec).div(price);        
        balances[msg.sender] = balances[msg.sender].add(numberofTokens); 


This contract is at 0xaaae538f158f3a0917ba466c33ab84a7976249c9 you can see two transactions one buying and one selling.

From your screenshot I see that the contract says that no tokens were sold, therefore I do not understand what tokens are you selling back. Look that in your contract the variable totalSold = 0.

In summary, the error seems to be that there is no ether in your contract to be sent.

  • I used your code you said, function names are not changed and when I buy token that was done successfully, but when I tried to return that is giving error again. screenshot: prntscr.com/j388mb Apr 10, 2018 at 8:46
  • I just edited the answer. In short seems that your contract has no ether. The functions work as expected.
    – Jaime
    Apr 10, 2018 at 10:11
  • Let me know how it goes
    – Jaime
    Apr 10, 2018 at 10:16
  • Thanks. Finally, I got the problem in my code as when someone buy the token I was sending ether to owner account in buy() function like this owner.transfer(msg.value); after when someone wants to return the token that tries to deduct ethers from contract ethers and ether balance of contract is zero so this issue comes up. So I removed owner.transfer(msg.value); in buy and that is working fine now. Can you please suggest what is the best approach to send ether in case of buy() and if I want to owner account then how can I deduct from owner/deployer account instead of contract address? Apr 10, 2018 at 12:28
  • 1
    I think the best solution is to leave the ether in the contract for several reasons: 1. If the contract is safe leaving the ether there avoid to pay for the transactions. 2. Trust, if the users see that you are taking the ether to your private account they will not trust the contract, because to be able to sell the token they will require you to agree not just the code of the contract. If I answered your question, please accept it by clicking on the check mark. Good luck
    – Jaime
    Apr 10, 2018 at 12:58

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.