gpt4 book ai didi

solidity - 从 Keeper 更改合约 B 的变量状态

转载 作者:行者123 更新时间:2023-12-05 02:37:28 25 4
gpt4 key购买 nike

目的是使用B合约中的这个变量我尝试使用委托(delegate)调用但不起作用,仅适用于事件

契约(Contract)B.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;
}
}

计数器.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对合约B执行delegatecall时,B的代码与合约一起执行>A 的存储,msg.sendermsg.value。存储、当前地址和余额仍然引用调用合约(contract A),只是code取自被调用地址(contract B)。

在您的例子中,setTokenName 更新了 ContractBtokenName,因此 ContractB 的存储槽 0。 Counter 智能合约中相同的存储槽是uint256 public counter。当您执行 delegatecall 时,您使用 ContractB 更新了 Counter 的存储(counter 变量) setTokenName函数逻辑。

既然你知道 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);
}
}

关于solidity - 从 Keeper 更改合约 B 的变量状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69976064/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com