I'm looking for help to build an intermediate contract using delegatecall. My challenge would be with 3 contracts.
I need contract A to be the owner of Contract B, and contract B to have a transferownership function to transfer to another address but to be only owner, the role of contract C will be as an intermediary, contract A must make a call to C and the C delegatecall to the B.
The function to be performed on B is onlyowner, so only A could do it, but it needs an intermediate contract.
I was trying with this test:
// SPDX-License-Identifier: MIT
// ContratoA.sol
pragma solidity ^0.8.0;
import "./ContratoC.sol"; // Importe o ContratoC aqui
contract ContratoA {
address public owner;
address public contratoB;
address public contratoC;
modifier onlyOwner() {
require(msg.sender == owner, "Somente o proprietario pode chamar esta funcao ESTOUNOCONTRATOA");
_;
}
event ContratoBIncluido(address indexed contratoB);
event ContratoCIncluido(address indexed contratoC);
event OwnershipTransferAttempt(address indexed newOwner, bool success);
constructor() {
owner = msg.sender;
}
function incluirContratoB(address _enderecoContratoB) public onlyOwner {
contratoB = _enderecoContratoB;
emit ContratoBIncluido(contratoB);
}
function incluirContratoC(address _enderecoContratoC) public onlyOwner {
contratoC = _enderecoContratoC;
emit ContratoCIncluido(contratoC);
}
// Função para chamar transferOwnershipContratoB no Contrato C
function transferOwnershipContratoB(address newOwner) public onlyOwner {
require(contratoC != address(0), "Endereco do Contrato C nao configurado");
emit OwnershipTransferAttempt(newOwner, false);
ContratoC contratoCInstance = ContratoC(contratoC);
contratoCInstance.transferOwnershipContratoB(newOwner);
emit OwnershipTransferAttempt(newOwner, true);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ContratoB {
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Somente o proprietario pode chamar essa funcaoESTOUNOCONTRATOB");
_;
}
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
owner = msg.sender;
}
function transferOwnership(address newOwner) public onlyOwner {
emit OwnershipTransferred(owner, newOwner);
require(newOwner != address(0), "Endereco invalido");
address previousOwner = owner;
owner = newOwner;
emit OwnershipTransferred(previousOwner, newOwner);
}
function getOwner() public view returns (address) {
return owner;
}
}
// SPDX-License-Identifier: MIT
// ContratoC.sol
pragma solidity ^0.8.0;
import "./ContratoB.sol";
contract ContratoC {
address public contratoA;
event BeforeDelegateCall(address newOwner);
event AfterDelegateCall(bool success, bytes data);
event DelegateCallData(bytes data); // Declaração do evento adicionada
modifier onlyContratoA() {
require(msg.sender == contratoA, "Somente o Contrato A pode chamar essa funcao CONTRATOC");
_;
}
constructor() {
// ContratoA ainda não está definido ao criar ContratoC
}
function setContratoA(address _contratoA) public {
require(_contratoA != address(0), "Endereco do Contrato A invalido");
contratoA = _contratoA;
}
function transferOwnershipContratoB(address newOwner) public onlyContratoA {
require(contratoA != address(0), "Endereco do Contrato A nao configurado");
emit BeforeDelegateCall(newOwner);
(bool success, bytes memory data) = contratoA.delegatecall(
abi.encodeWithSignature("transferOwnership(address)", newOwner)
);
// Adiciona logs adicionais para depuração
emit AfterDelegateCall(success, data);
emit DelegateCallData(data);
require(success, "Chamada para o Contrato A falhou");
}
// ...
}