I'm trying to develop a smart-contract where people can publish and get paid by it, i want the person get paid in the token of the platform not in eth. Without using the token the contract works ok, but when i try adding the contract doesn't works.
Thats the Token code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Capped.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract NewsToken is ERC20Capped, ERC20Burnable {
address payable public owner;
uint256 public blockReward;
mapping(address => bool) public validators;
constructor(uint256 cap, uint256 reward) ERC20("News Token", "NWT") ERC20Capped(cap * (10 ** decimals())) {
owner = payable(msg.sender);
_mint(owner, 70000000 * (10 ** decimals()));
blockReward = reward * (10 ** decimals());
}
function _mint(address account, uint256 amount) internal virtual override(ERC20Capped, ERC20) {
require(ERC20.totalSupply() + amount <= cap(), "ERC20Capped: cap exceeded");
super._mint(account, amount);
}
function _mintMinerReward() internal {
_mint(block.coinbase, blockReward);
}
function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual override {
if(from != address(0) && to != block.coinbase && block.coinbase != address(0)) {
_mintMinerReward();
}
super._beforeTokenTransfer(from, to, value);
}
function setBlockReward(uint256 reward) public onlyOwner {
blockReward = reward * (10 ** decimals());
}
function destroy() public onlyOwner {
selfdestruct(owner);
}
function becomeValidator() public {
require(balanceOf(msg.sender)>=1000000 * (10 ** decimals()), "You need at least 1.000.000 tokens to become a validator");
validators[msg.sender] = true;
}
function removeValidator() public {
require(validators[msg.sender], "You are not a validator");
validators[msg.sender] = false;
}
function checkValidator() public view returns (bool){
return validators[msg.sender];
}
modifier onlyOwner {
require(msg.sender == owner, "Only the owner can call this function");
_;
}
function callApprove(address _sender,address _writer, uint256 _amount) public {
_sender.approve(_writer, _amount);
}
}
Thats the Contract code:
//contracts/Web3News.sol
//SPDX-License-Identifier: MIT
import "./paymentManager.sol";
import "./NewsToken.sol";
pragma solidity ^0.8.17;
contract Web3News{
address public writer;
string public title;
string public topics;
string private subject;
string private Autentic = "O artigo e verdadeiro";
string private Fake = "O artigo e Falso";
uint public minimumPayment;
uint public itsAutentic;
uint public itsFake;
mapping(address => bool) public buyers;
//Importa o contrato do NewsToken e do PaymentManager
NewsToken public newsToken;
//PaymentManager public paymentManager;
event LogSecretAccess(address indexed sender);
constructor(address _newsTokenAddr, string memory _title, string memory _topics, string memory _subject, uint _minimumPayment){
writer = msg.sender;
title = _title;
topics = _topics;
subject = _subject;
minimumPayment = _minimumPayment;
newsToken = NewsToken(_newsTokenAddr);
//paymentManager = PaymentManager(_paymentManagerAddr);
}
//Da acesso do conteudo do artigo para quem pagar
//function getAccessToArticle() public payable{
//Verifica no contrato do NewsToken se o usuario tem saldo suficiente para pagar a taxa minima
// require(newsToken.balanceOf(msg.sender) >= minimumPayment, "Not enough tokens.");
//Faz o pagamento do artigo para o contrato do PaymentManager que manda o pagamento ao criador do artigo
//newsToken.approve(address(this), minimumPayment);
//require(newsToken.allowance(msg.sender, address(this)) >= minimumPayment, "You have not approved the contract to transfer the tokens");
// newsToken.transferFrom(msg.sender, writer, minimumPayment);
// buyers[msg.sender] = true;
//paymentManager.payForNews(address(this), minimumPayment);
//}
function getAccessToArticle1() public payable {
require(newsToken.balanceOf(msg.sender) >= minimumPayment, "Not enough tokens");
newsToken.approve(address(this), minimumPayment);
//chamar uma funcao que transfere os fundos do msg.sender pra o contrato?
newsToken.transferFrom(msg.sender, writer, minimumPayment);
//newsToken.transfer(tx.origin, minimumPayment);
buyers[msg.sender] = true;
}
//function getAccessToArticle() public payable {
// require(newsToken.balanceOf(msg.sender) >= minimumPayment, "Not enough tokens.");
//address tokenContractAddress = address(newsToken);
//bytes memory data = abi.encodeWithSignature("transfer(address,uint256)", address(writer), minimumPayment);
//(bool success, bytes memory returnedData) = tokenContractAddress.call(data);
//require(success, "The call to the transfer function was not successful.");
//buyers[msg.sender] = true;
//}
//Puxa o conteudo do artigo para o usuario caso o mesmo tenha pago a taxa minima para acessar o artigo
function readArticle() public returns (string memory) {
//Verifica no contrato do PaymentManager se o usuario se encontra na lista de compradores
require(buyers[msg.sender], "This address haven't purchased the article");
emit LogSecretAccess(msg.sender);
return subject;
}
//Funcao para votar como fakenews
function fakenews(bool _itsAutentic) public {
require(buyers[msg.sender], "This address haven't purchased the article, so it can't vote");
if (_itsAutentic) {
itsAutentic = itsAutentic + 1;
} else {
itsFake = itsFake + 1;
}
}
//Funcao para julgar se e ou nao fakenews. Deve ser ativada somente por um autenticador/delegado
function judgement() public view returns (string memory) {
//Verifica se o endereco que esta chamando a funcao e um autenticador na lista de autenticadores do NewsToken
require(newsToken.checkValidator(), "This address is not a validator");
if (itsAutentic > itsFake) {
return Autentic;
} else {
return Fake;
}
}
//Funcao para punir quem autenticar a noticia de forma erronea
}
I know that the problem is: when calling the transfer method on the token the address that is calling the function is the address of the contract and not the msg.sender, i had try the call(), the delegatecall(), and other methods. It's not clear to me how can i sove that, hopping some one can help me here...
After some time I discovered what is the problem, to make the token transaction I need to approve the contract address on the token contract so I can call the .transferFrom
in the other contract!
On the token contract
Aprove(contractAddress,amount);
On the contract ir self
token.tranferFrom(adress1, adress2, amount);