Search code examples
ethereumsoliditysmartcontracts

How do you define operator when creating new ERC-777?


My understanding is that you can define an operator when instantiating a custom ERC-777, that can make transfers without needing to be approved by the senders using the operatorSend function. However, can't seem to get the address of the contract that deploys the token into the inherited constructor. I tried pushing the address into the array in the body of the constructor, but that doesn't seem to take.

contract MainToken is ERC777 {
    address[] ops=;
  constructor ()  ERC777("MYTOKEN", "MTK",ops) {
      ops.push(msg.sender);
    }
...
}

If I try putting it directly into the constructor like so ERC777("MYTOKEN", "MTK",[msg.sender]), I get

Invalid type for argument in modifier invocation. Invalid implicit conversion from address[1] memory to address[] memory requested.


Solution

  • Solidity currently doesn't allow defining a dynamic-size array in one expression. Note: [msg.sender] from your example is a fixed-size array definition.

    Also, your approach with defining the ops property doesn't work, because of the order how EVM processes the constructor.

    1. Storing child (MainToken) constructor arguments to memory (in your case no arguments)

    2. Executing parent constructor.

      In your case the execution of ERC777("MYTOKEN", "MTK", ops) fails, because the storage variable ops is not available yet.

    3. Executing child constructor (in your case ops.push(msg.sender);)


    So the easiest Solution I could come up with, is passing the address from the MyToken argument. This is useful if you have control over the deployment process and can manually pass the value of msg.sender when you're deploying the contract.

    pragma solidity 0.8.4;
    
    import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC777/ERC777.sol';
    
    contract MyToken is ERC777 {
    
        constructor(address[] memory defaultOperators)
            ERC777('MYTOKEN', 'MTK', defaultOperators) {
        }
    
    }
    

    If you're not going to have control over the deployment and need to assign msg.sender in constructor, I suggest copying the ERC777 contract locally and modifying its constructor, so that it only adds the msg.sender.