I've seen 2 solutions here and they worked for others but they aren't working for me. I have no problem transferring ownership to the crowdsale, but how do I code it to be able to transfer the ownership of the token back to my main account?

I've created a function for it, and it gives me no errors, it even executes with no problem, but it never changes the ownership. Here's the partial code of my crowdsale:

pragma solidity ^0.4.16;

 * @title Owned
 * @dev The Owned contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
contract Owned {
  address public owner;

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  event TokenOwnershipTransferred(address indexed _newOwner, address indexed _previousOwner);

   * @dev The Owned constructor sets the original `owner` of the contract to the sender
   * account.
  function Owned() public {
    owner = msg.sender;

   * @dev Throws if called by any account other than the owner.
  modifier onlyOwner() {
    require(msg.sender == owner);

   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    emit OwnershipTransferred(owner, newOwner);
    owner = newOwner;

    function transferTokenOwnership(address _newOwner) public onlyOwner {
    require(_newOwner != address(0));
     emit TokenOwnershipTransferred(owner, _newOwner);
     owner = _newOwner;


interface token {
    function mint(address receiver, uint amount) external;


library SafeMath {

  * @dev Multiplies two numbers, throws on overflow.
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    uint256 c = a * b;
    assert(c / a == b);
    return c;

  * @dev Integer division of two numbers, truncating the quotient.
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;

  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;

  * @dev Adds two numbers, throws on overflow.
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;

contract FCCCrowdsale is Owned{
    using SafeMath for uint256;

    address public beneficiary;
    uint256 public fundingGoal;
    uint256 public amountRaised;
    uint256 public openingTime;
    uint256 public closingTime;
    uint256 public initialRate;
    uint256 public finalRate;
    token public tokenReward;

    mapping(address => uint256) public balanceOf;

    bool fundingGoalReached = false;
    bool crowdsaleClosed = false;

    event GoalReached(address recipient, uint totalAmountRaised);
    event FundTransfer(address backer, uint amount, bool isContribution);

      event Closed();
  • Can you give more details as to how you're trying to call the function to transfer ownership back? Also im not sure why you have two different transfer ownership functions? There's no clear reason as to why you chose those two, and I suspect that's probably why you're running into an issue, but without more information as to how you're passing hte ownership off initially, and how you're trying to pass it back its not possible to find a solution. – hextet Mar 28 '18 at 21:44
  • 1 function serves the purpose of transferring the ownership of the crowdsale contract and the 2nd to transfer the ownership of the actual token. I have no intention of ever transferring ownership of the crowdsale, but I'm not sure why that would create issues in trying to transfer the token itself. I could try it with just one, but the crowdsale indeed needs to be owned. – shyheim103 Mar 29 '18 at 12:59

As @btc4cash said, you can not, unless you write the crowd-sale contract in such a manner that it can transfer ownership back.

Check out this sample code:

pragma solidity ^0.4.17;

contract Token{
    address public owner;

    function transferOwnerShip(address _newOwner) public {
        require (msg.sender == owner);
        owner = _newOwner;

    function Token() public{
        owner = msg.sender;

contract Crowdsale{
    Token tokenContract;
    address crowdsaleOwner;

    function Crowdsale(address _tokenAddress) public {
      tokenContract = Token(_tokenAddress);
      crowdsaleOwner = msg.sender;

    function transferOwnerShipBack(address _newOwner) public {
        require(msg.sender == crowdsaleOwner);

You can execute transferOwnerShipBack method of crowdsale contract to transfer ownership to a new user.

PS: This was just for the demo purpose. Test before use in production.

Edit 1: Explanation on the Code works Since it is very clear that smart contracts can only execute what their code allows. SO if you need to transfer ownership to your crowdsale contract, the crowdsale contract must have a method to transfer ownership back. The above code sample does exactly the same.

Let me make this very clear, there are 2 contracts Token and Crowdsale and both needs to be deployed separately.

  • Open Remix Compiler (or choose other methods if you want)
  • Paste the above code into the editor
  • There you have 5 accounts (if using Javascript VM). Let's call accounts with Acc1, Acc2 ...
  • Deploy Token contract from Acc1.
  • Copy Token contract address and pass this as constructor argument while deploying Crowdsale contract. Deploy Crowdsale contract from Acc2.
  • Call transferOwnership method of Token Contact from Acc1 and transfer Ownership to Crowdsale Contract.
  • Now you can check the owner of Token contract is the Crowdsale Contract.
  • Now if you need to transfer back the ownership of Token COntract to Acc1. JUst call transferOwnershipBack of Crowdsale Contract from Acc2, passing Acc1 as an argument.

I have taken an example of multiple accounts just to show that both contracts are independent can will behave even if have different owners. You can do all the same with a single account as well if you don't want to complicate things.

| improve this answer | |
  • Thanks Prashant, I'm going to try this. The other solution said to do pretty much the same thing but wasn't as comprehensive as your example. I'll let you know how it works out! – shyheim103 Mar 29 '18 at 14:15
  • OK so I tried that, and it's giving me an TypeError: Member "transferOwnership" not found or not visible after argument-dependent lookup in contract Token tokenContract.transferOwnership. I'm going to try something else. I think it may have to do with the @param comments. – shyheim103 Mar 29 '18 at 15:05
  • Got rid of the errors, deployed it and now it's giving me an always failing transaction or gas limit too high. I'm stumped. – shyheim103 Mar 29 '18 at 15:20
  • This is not a valid issue. Obly thing that change on the transfer ownership back function is that the modifier onlyOwner was remplaced by requiring the sender been the contract owner, which is the SAME. Very weak answer. – btc4cash Mar 29 '18 at 15:44
  • Yeah, the new function was exactly the same. This is why it looped and wouldn't execute. I figured that out and was going to come back and comment on it once I got things sorted. – shyheim103 Mar 29 '18 at 16:33

You cannot.


As I said, what I do is the ICO create the token in constructor, and constructor of the token itself accept the ICO address as the parameter. This way you have an owner AND the ICO address in the token.

Actual code I see is only owner can transfer the ownership, and not to himself. So once transfered, only the new owner can transfer the ownership back because of the onlyOwner modifier.

If there was not this modifier, anyone could transfer ownership which is obliviously not a good idea :)

| improve this answer | |
  • Exactly, I definitely don't want that. But there are people who have pulled this off, but for some reason their string doesn't work. Here is a link to a solution, but I can't see what i'm doing wrong. :ethereum.stackexchange.com/questions/34184/… – shyheim103 Mar 29 '18 at 13:01
  • I just checked link its a non sense as well. Contract cannot call by itself a function someone need to call it. So even giving the ownership to the contract itself will still have the issue than anyone would be able to transfer back the owner ship to pevious owner anytime or worst to themself. – btc4cash Mar 29 '18 at 15:51
  • 1
    Exactly. I saw one instance where someone said it worked. However, I can't find that thread anymore but the code was very similar if not exact. I have managed twice now, coding it different ways to get it to actually execute the function, it just doesn't give the ownership to the new address, the crowdsale keeps giving the ownership back to itself. And it needs to be an "onlyOwner" function, otherwise my sale/token would be doomed. I may just have to look at this another way and just do a fixed sale and not a mintable one. – shyheim103 Mar 29 '18 at 16:30
  • If you find send me :) what I do publish ICO, the contrcutor of it create the token and suppliy owner AND ICO address, this way ICO can mint token. :) – btc4cash Mar 29 '18 at 16:32
  • I have it setup that way, but I still want control over the tokens after the fact. Let's say if there is some investigation and the government requests my help of an account they're tracing, I can freeze it. Or (because I'm creating a marketplace), let's say a seller sends a buyer a product not as described; but they already cashed out their token. I could still reimburse the buyer buy minting new tokens and freeze the seller's account indefinitely. – shyheim103 Mar 29 '18 at 19:18

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.