Solidity

使用 dapptools 編寫測試時,如何將交易作為特定錢包地址發送?

  • January 25, 2022

我在玩 dapptools:dapp

我想編寫一個測試來檢查 OpenZeppelin 的 ERC721transferFrom(..)函式實現的氣體。

這是我的測試:

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.6;

import "ds-test/test.sol";

import "./DemoErc721.sol";

contract DemoErc721Test is DSTest {

   DemoErc721 a;
   address testWallet = address(0x7E67aF7FF72cb87b7B0100cA8128F4673D185234);
   address testWallet2 = address(0x7E67af7FF72Cb87B7b0100ca8128f4673D185235);

   function setUp() public {
       a = new DemoErc721();
   }

   function mintMultiple(uint256 numToMint) public {
       a.mint(testWallet, numToMint);
       assertEq(a.balanceOf(testWallet), numToMint);
   }

   function testMint_1() public {
       mintMultiple(1);
   }
   function testMint_2() public {
       mintMultiple(2);
   }
   function testMint_3() public {
       mintMultiple(3);
   }
   function testMint_4() public {
       mintMultiple(4);
   }
   function testMint_5() public {
       mintMultiple(5);
   }

   function testTransfer() public {
       mintMultiple(1);
       a.transferFrom(testWallet, testWallet2, 1);
   }
}

您可以在mintMultiple函式中看到,我們總是在向testWallet地址鑄造代幣。

所以在最後的測試中testTransfer(),我希望能夠從testWallet另一個錢包轉移,因為testWallet是 NFT 的所有者,擁有 tokenId 1

但是,我認為我編寫此測試的方式導致呼叫地址成為此測試合約的地址,而不是testWallet地址。

Hardhat 中的類似邏輯是這樣的:

最後,要從另一個帳戶執行合約的方法,您需要做的就是將合約與正在執行的方法連接起來:

await greeter.connect(addr1).setGreeting("Hallo, Erde!");

所以我的問題是,如何模擬transferFrom從 進行函式呼叫testWallet

根據推特上的@transmissions11

你不能 - 可以創建一個測試使用者合約或使用 Foundry,它有一個 .prank() 作弊碼

https://github.com/gakonst/foundry

您可以創建另一個名為TokenUser. 在建構子中使用令牌實例對其進行初始化。現在,定義使用者可以對令牌進行的呼叫並圍繞它編寫一個包裝函式。像這樣的東西

contract TokenUser{

   Token  token;

   constructor(Token token_) public {
       token = token_;
   }

   function doTransfer(address to, uint amount) public returns (bool){
       return token.transfer(to, amount);
   }
   
   ...

   //other functions

}

現在在setUp()測試合約中,創建一個令牌實例並將地址傳遞給使用者。

contract TokenTest is DSTest{

   Token token;
   TokenUser user1;
   TokenUser user2;

   function setUp() public {
      token = new Token("[required_inputs]");
      user1 = new TokenUser(token);
      user2 = new TokenUser(token);
   }

   // rest of the contract
   
}

對於測試功能,您可以使用使用者實例

function testSomething() public {
   user1.transfer(address(user2),100);
   user2.approve(address(user1),100);
}

該方法可用於模擬從不同賬戶(賬戶為不同的TokenUser合約)發送交易。dapphub 有一個優雅的實現範例,你可以在這裡找到它。

引用自:https://ethereum.stackexchange.com/questions/118808