从Keeper更改合同B的变量的状态



目的是使用B合同中的此变量我正在尝试使用代理呼叫,但不起作用,只能使用事件

ContractB.sol

// SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
contract ContractB {

uint256 public tokenName = uint256(2);
event SetToken(uint256 _tokenName); 
function setTokenName(uint256 _newName) external returns (uint256) {                
setInternal(_newName);  
}

function setInternal (uint256 _newName) public returns (uint256)
{
tokenName = _newName;
emit SetToken(tokenName);
return tokenName;
}

function getTokenName() public view returns (uint256)
{
return tokenName;
}        
}

Counter.sol

//Begin
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface KeeperCompatibleInterface {
function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
function performUpkeep(bytes calldata performData) external;
}
contract Counter is KeeperCompatibleInterface {

uint256 public counter;    // Public counter variable
// Use an interval in seconds and a timestamp to slow execution of Upkeep
//60 seconds
uint public immutable interval;
uint public lastTimeStamp;  //My counter was updated  

//**
address contractBAddress;
uint256 public tokenName = uint256(2);
//**

constructor(uint updateInterval,address _contractBAddress) {
interval = updateInterval;
lastTimeStamp = block.timestamp;
counter = 0;
contractBAddress=_contractBAddress;
}
function checkUpkeep(bytes calldata checkData) external view override returns (bool upkeepNeeded, bytes memory performData) {
upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;
performData = checkData;
}

//When checkUpKeep its already to launch, this task is executed
function performUpkeep(bytes calldata) external override {
lastTimeStamp = block.timestamp;
counter=0;
counter = counter + 1;
(bool success, bytes memory returndata) = contractBAddress.delegatecall(
abi.encodeWithSignature("setTokenName(uint256)", counter)
);
// if the function call reverted
if (success == false) {
// if there is a return reason string
if (returndata.length > 0) {
// bubble up any reason for revert
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert("Function call reverted");
}
}
}
function getTokenName() public view returns (uint256)
{
return tokenName;
}

}

该活动运行良好,但我无法更改ContractB.sol中的状态。。。https://kovan.etherscan.io/tx/0x7fbacd6fa79d73b3b3233e955c9b95ae83efe2149002d1561c696061f6b1695e#eventlog

事件完美运行的事实证明Keeper做得很好。这里的问题是delegatecall本身。

当合约A执行delegatecall到合约B时,B的代码与合约A的存储器msg.sendermsg.value一起执行。存储、当前地址和余额仍然参考调用合同(合同A(,仅代码取自调用地址(合同B(。

在您的情况下,setTokenName更新ContractBtokenName,而不是ContractB的存储插槽0。Counter智能合约的同一存储插槽为uint256 public counter。执行delegatecall时,使用ContractBsetTokenName函数逻辑更新了Counter的存储(counter变量(。

既然你知道ContractB的ABI,为什么不做这样的事情呢?

pragma solidity ^0.8.0;
import "./ContractB.sol";
contract Counter is KeeperCompatibleInterface {
ContractB public contractB;
uint256 public counter;
constructor(ContractB _contractBAddress) {
contractB = _contractBAddress;
}
function performUpkeep(bytes calldata) external override {
counter = counter + 1;
contractB.setTokenName(counter);
}
}

您应该使用这个:

ContractB contractB = ContractB(contractBAddress);
contractB.setTokenName(counter);

文件:https://solidity-by-example.org/calling-contract/

Counter.sol

//Begin
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface KeeperCompatibleInterface {
function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
function performUpkeep(bytes calldata performData) external;
}
contract Counter is KeeperCompatibleInterface {

uint256 public counter;    // Public counter variable
// Use an interval in seconds and a timestamp to slow execution of Upkeep
//60 seconds
uint public immutable interval;
uint public lastTimeStamp;  //My counter was updated  

//**
address public contractBAddress;
//**

constructor(uint updateInterval,address _contractBAddress) {
interval = updateInterval;
lastTimeStamp = block.timestamp;
counter = 0;
contractBAddress=_contractBAddress;
}
function checkUpkeep(bytes calldata checkData) external view override returns (bool upkeepNeeded, bytes memory performData) {
upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;
performData = checkData;
}

//When checkUpKeep its already to launch, this task is executed
function performUpkeep(bytes calldata) external override {
lastTimeStamp = block.timestamp;
counter = counter + 1;
ContractB contractB = ContractB(contractBAddress);
contractB.setTokenName(counter);
}

}

ContractB.sol

contract ContractB {

uint256 public tokenName = uint256(2);
function setTokenName(uint256 _newName) external {                
tokenName=_newName;
}


function getTokenName() public view returns (uint256)
{
return tokenName;
}

}

最新更新