测试ChainLinkClient回调 - 如何绕过RecordChainLinkfulflyment?
我有一个链链链接客户合同,可以直接到Oracle。 Oracle做了它的事情,然后通过ChaineLinkRinkRequest
通过的典型回调选择器返回答案。一切都很好,但是我想编写一些测试测试回调实现的测试,
我的客户合同如下:
contract PriceFeed is Ownable, ChainlinkClient {
function updatePrice() onlyOwner returns (bytes32 requestId) {
// makes Chainlink request specifying callback via this.requestCallback.selector
}
function requestCallback(bytes32 _requestId, uint256 _newPrice) public
recordChainlinkFulfillment(_requestId) {
price = _newPrice;
}
}
当测试代码调用requestcallback(...)
和代码时出现问题。点击RecordChainLinkfulFillment(...)
修饰符。 chainlinkclient
抱怨requestID
由下面的测试传递给了pendendRequests
由chaine> chainelinkclclient维护的映射
。
ChainLinkClient
的简化版本看起来像:
contract ChainlinkClient {
mapping(bytes32 => address) private pendingRequests;
modifier recordChainlinkFulfillment(bytes32 _requestId) {
require(msg.sender == pendingRequests[_requestId], "Source must be the oracle of the request");
delete pendingRequests[_requestId];
emit ChainlinkFulfilled(_requestId);
_;
}
}
我的铸造/固体测试如下:
contract PriceFeedTest is Test {
function testInitialCallback() public {
priceFeed.requestCallback("abc123", 1000000); // fails on this line
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
代码在testInitialCallback()的第一行中失败:必须是请求的oracle
我如何欺骗链链接限额允许我的回调超越修饰符检查? AFAIK我无法访问和预先填充私有pendingRequests
映射。还有另一种方法吗?
我知道Foundry提供了作弊码来帮助测试,并且有一个stdstorage作弊码,但是我在如何构建对stdstorage的呼叫以覆盖pendingRequests时并不熟悉。
contract PriceFeedTest is Test {
function testInitialCallback2() public {
stdstore
.target(address(priceFeed))
.sig("pendingRequests()")
.with_key("abc123")
.checked_write(address(this));
priceFeed.requestCallback("abc123", 1000000);
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
以上代码会引发以下错误:未检测到目标的存储使用
任何帮助将不胜感激。非常感谢。
I've got a Chainlink client contract which makes a DirectRequest to an oracle. The oracle does its thing and then returns the answer via the typical callback selector passed in via the ChainlinkRequest
. It all works well, but I'd like to write some tests that test the callback implementation
My client contract is as follows:
contract PriceFeed is Ownable, ChainlinkClient {
function updatePrice() onlyOwner returns (bytes32 requestId) {
// makes Chainlink request specifying callback via this.requestCallback.selector
}
function requestCallback(bytes32 _requestId, uint256 _newPrice) public
recordChainlinkFulfillment(_requestId) {
price = _newPrice;
}
}
The problem arises when the test code calls requestCallback(...)
and the code hits the recordChainlinkFulfillment(...)
modifier. The ChainlinkClient
complains that the requestId
being passed in by the test below isn't in the underling private pendingRequests
mapping maintained by the ChainlinkClient
.
The simplified version of ChainlinkClient
looks like this:
contract ChainlinkClient {
mapping(bytes32 => address) private pendingRequests;
modifier recordChainlinkFulfillment(bytes32 _requestId) {
require(msg.sender == pendingRequests[_requestId], "Source must be the oracle of the request");
delete pendingRequests[_requestId];
emit ChainlinkFulfilled(_requestId);
_;
}
}
My Foundry/Solidity test is as follows:
contract PriceFeedTest is Test {
function testInitialCallback() public {
priceFeed.requestCallback("abc123", 1000000); // fails on this line
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
The code fails on first line of the testInitialCallback()
line with: Source must be the oracle of the request
How can I trick the ChainklinkClient into allowing my callback to get past the modifier check? AFAIK I can't access and pre-populate the private pendingRequests
mapping. Is there another way?
I know that Foundry provides Cheatcodes to help in testing and there's a stdstorage cheatcode, but I'm not familiar on how to construct a call to stdstorage to override pendingRequests if thats even possible with a cheatcode.
contract PriceFeedTest is Test {
function testInitialCallback2() public {
stdstore
.target(address(priceFeed))
.sig("pendingRequests()")
.with_key("abc123")
.checked_write(address(this));
priceFeed.requestCallback("abc123", 1000000);
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
The above code throws the following error: No storage use detected for target
Any help would be greatly appreciated. Many thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您在测试中执行
updatePrice
功能时,您应该能够从交易收据事件中删除requestID
。一旦拥有,您就可以在requestCallback
中使用它。 Check out this example unit test从硬汉入门套件中When you execute the
updatePrice
function in your test, you should be able to strip out therequestId
from the transaction receipt event. Once you have that, you can then use it in your call torequestCallback
. Check out this example unit test from the hardhat starter kit for an example of this