0

I'm using OpenZeppelin as base for my contracts.

I know it don't allow me to access _balances directly, only using transfer(). But this function only allow transfer tokens from/to the sender, hidding the original transfer():

function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
} 

function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
}

This way I can't access _balances[] directly and it is a GOOD thing! But ....

I have an use case that I really need to access _balances[] or someone shows me another way to do it. Let's see :

  • I have 4 tokens: Gold, Wood, Iron and Clay.
  • Gold is the only owner of the other 3 ( Gold created them in its constructor ).
  • I need to call 3 functions in Gold contract to give to user Wood, Iron and Clay in exchange of Gold. The user call buyWood( goldAmount ), buyIron( goldAmount ) and buyClay( goldAmount )and I need to take goldAmount from his Gold balance and put goldAmount ( 1:1 for now) in his resource balance calling each resource's methods.
  • In other hand when the user calls sell(amount) in any resource I need to take the way back giving him this amount in Gold ( 1:1 for now) and take back this amount in resources from his resource balance.

My problem is: since I can't handle internal balance map directly, I'm messing something with OpenZeppelin's transfer() wrapper function. Also tried transferFrom() but things only got worse.

The error I'm receiving is something like "The sender cannot be null" (I can't check it right now) in "buy***()" methods.

Here is the code:

Gold.sol

pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/access/Ownable.sol";
import "./resource.sol";

contract Gold is Ownable, ERC20 {
    Resource public _wood;
    Resource public _iron;
    Resource public _clay;

    constructor ()  ERC20("Gold", "W-GLD") {
        _mint( msg.sender, 1000 * (10 ** uint256( decimals() ) ) );
        _wood = new Resource("Wood", "W-WOD");
        _iron = new Resource("Iron", "W-IRN");
        _clay = new Resource("Clay", "W-CLY");
    }

    function buyWood(uint _value) external {
        transferFrom(msg.sender, owner(), _value);
        _wood._give(msg.sender, _value);
    }
    
    function buyIron(uint _value) external {
        transferFrom(msg.sender, owner(), _value);
        _iron._give(msg.sender, _value);
    }

    function buyClay(uint _value) external {
        transferFrom(msg.sender, owner(), _value);
        _clay._give(msg.sender, _value);
    }
    
    function _give( address _to, uint _value ) external {
        require( msg.sender == address( _wood ) || msg.sender == address( _clay ) || msg.sender == address( _iron ) );
        transferFrom( owner(), _to, _value );
    }    

    function decimals() public view virtual override returns (uint8) {
        return 5;
    }  
}

Resource.sol

pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/access/Ownable.sol";
import "./gold.sol";

contract Resource is Ownable, ERC20 {

    
    constructor (string memory name, string memory symbol ) ERC20(name,symbol) {
        
    }
    
    function _give(address _to, uint _value) external onlyOwner {
        transferFrom( owner(),  _to, _value );
    } 
    
    function sell(uint _value) external {
        transferFrom(msg.sender, owner(), _value);
        Gold( owner() )._give(msg.sender, _value);
    } 
    
  
    
}

1 Answer 1

0

Ooops!! My code is correct. I just forgot to mint some coins in the Resource's constructor ...

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.