坚固 - 测试合同时签署铸造
我正在尝试围绕合同进行测试,但是我在了解如何在测试环境中签名的问题遇到问题,
这是我的合同
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.9 <0.9.0;
import "@divergencetech/ethier/contracts/crypto/SignatureChecker.sol";
import "@divergencetech/ethier/contracts/crypto/SignerManager.sol";
import "@divergencetech/ethier/contracts/erc721/BaseTokenURI.sol";
import "@divergencetech/ethier/contracts/erc721/ERC721ACommon.sol";
import "@divergencetech/ethier/contracts/erc721/ERC721Redeemer.sol";
import "@divergencetech/ethier/contracts/sales/FixedPriceSeller.sol";
import "@divergencetech/ethier/contracts/utils/Monotonic.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
interface ITokenURIGenerator {
function tokenURI(uint256 tokenId) external view returns (string memory);
}
// @author divergence.xyz
contract TestBirds is
ERC721ACommon,
BaseTokenURI,
FixedPriceSeller,
ERC2981,
AccessControlEnumerable
{
using EnumerableSet for EnumerableSet.AddressSet;
using ERC721Redeemer for ERC721Redeemer.Claims;
using Monotonic for Monotonic.Increaser;
/**
@notice Role of administrative users allowed to expel a Player from the
mission.
@dev See expelFromMission().
*/
bytes32 public constant EXPULSION_ROLE = keccak256("EXPULSION_ROLE");
constructor(
string memory name,
string memory symbol,
string memory baseTokenURI,
address payable beneficiary,
address payable royaltyReceiver
)
ERC721ACommon(name, symbol)
BaseTokenURI(baseTokenURI)
FixedPriceSeller(
2.5 ether,
Seller.SellerConfig({
totalInventory: 10_000,
lockTotalInventory: true,
maxPerAddress: 0,
maxPerTx: 0,
freeQuota: 125,
lockFreeQuota: false,
reserveFreeQuota: true
}),
beneficiary
)
{
_setDefaultRoyalty(royaltyReceiver, 1000);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/**
@dev Mint tokens purchased via the Seller.
*/
function _handlePurchase(
address to,
uint256 n,
bool
) internal override {
_safeMint(to, n);
}
/**
@dev Record of already-used signatures.
*/
mapping(bytes32 => bool) public usedMessages;
/**
@notice Mint tokens.
*/
function mintPublic(
address to,
bytes32 nonce,
bytes calldata sig
) external payable {
signers.requireValidSignature(
signaturePayload(to, nonce),
sig,
usedMessages
);
_purchase(to, 1);
}
function alreadyMinted(address to, bytes32 nonce)
external
view
returns (bool)
{
return
usedMessages[
SignatureChecker.generateMessage(signaturePayload(to, nonce))
];
}
/**
@dev Constructs the buffer that is hashed for validation with a minting
signature.
*/
function signaturePayload(address to, bytes32 nonce)
internal
pure
returns (bytes memory)
{
return abi.encodePacked(to, nonce);
}
/**
@dev Required override to select the correct baseTokenURI.
*/
function _baseURI()
internal
view
override(BaseTokenURI, ERC721A)
returns (string memory)
{
return BaseTokenURI._baseURI();
}
/**
@notice If set, contract to which tokenURI() calls are proxied.
*/
ITokenURIGenerator public renderingContract;
/**
@notice Sets the optional tokenURI override contract.
*/
function setRenderingContract(ITokenURIGenerator _contract)
external
onlyOwner
{
renderingContract = _contract;
}
/**
@notice If renderingContract is set then returns its tokenURI(tokenId)
return value, otherwise returns the standard baseTokenURI + tokenId.
*/
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
if (address(renderingContract) != address(0)) {
return renderingContract.tokenURI(tokenId);
}
return super.tokenURI(tokenId);
}
/**
@notice Sets the contract-wide royalty info.
*/
function setRoyaltyInfo(address receiver, uint96 feeBasisPoints)
external
onlyOwner
{
_setDefaultRoyalty(receiver, feeBasisPoints);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721ACommon, ERC2981, AccessControlEnumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
,但是当我尝试创建铸造测试时,我必须生成有效的签名...
这是测试
const { expect } = require('chai');
describe("TestBirds", function () {
it ("Should return correct name, URI, owner and beneficiary", async function () {
const [owner, addr1] = await hre.ethers.getSigners()
provider = ethers.provider
const TestBirdsContract = await hre.ethers.getContractFactory("TestBirds")
const testBirdsContractDeployed = await TestBirdsContract.deploy(
"TestBirds",
"APFP",
"https://test.url/",
owner.address,
owner.address)
console.log(await provider.getBalance(owner.address));
await testBirdsContractDeployed.deployed()
const nonce = await ethers.provider.getTransactionCount(owner.address, "latest")
await testBirdsContractDeployed.mintPublic(owner.address, nonce, signature???)
expect(await testBirdsContractDeployed.name()).to.equal("TestBirds")
expect(await testBirdsContractDeployed.tokenURI(0), "https://test.url/0")
expect(await testBirdsContractDeployed.ownerOf(0)).to.equal(owner.address)
})
})
我应该如何唱歌才能工作?没有标志,我无法测试合同。如果我从合同中删除签名参数,但这不是我想要的。
谢谢
I am trying to create a test around a contract, but I am having problems understanding how to sign it in a test environment
This is my contract
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.9 <0.9.0;
import "@divergencetech/ethier/contracts/crypto/SignatureChecker.sol";
import "@divergencetech/ethier/contracts/crypto/SignerManager.sol";
import "@divergencetech/ethier/contracts/erc721/BaseTokenURI.sol";
import "@divergencetech/ethier/contracts/erc721/ERC721ACommon.sol";
import "@divergencetech/ethier/contracts/erc721/ERC721Redeemer.sol";
import "@divergencetech/ethier/contracts/sales/FixedPriceSeller.sol";
import "@divergencetech/ethier/contracts/utils/Monotonic.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
interface ITokenURIGenerator {
function tokenURI(uint256 tokenId) external view returns (string memory);
}
// @author divergence.xyz
contract TestBirds is
ERC721ACommon,
BaseTokenURI,
FixedPriceSeller,
ERC2981,
AccessControlEnumerable
{
using EnumerableSet for EnumerableSet.AddressSet;
using ERC721Redeemer for ERC721Redeemer.Claims;
using Monotonic for Monotonic.Increaser;
/**
@notice Role of administrative users allowed to expel a Player from the
mission.
@dev See expelFromMission().
*/
bytes32 public constant EXPULSION_ROLE = keccak256("EXPULSION_ROLE");
constructor(
string memory name,
string memory symbol,
string memory baseTokenURI,
address payable beneficiary,
address payable royaltyReceiver
)
ERC721ACommon(name, symbol)
BaseTokenURI(baseTokenURI)
FixedPriceSeller(
2.5 ether,
Seller.SellerConfig({
totalInventory: 10_000,
lockTotalInventory: true,
maxPerAddress: 0,
maxPerTx: 0,
freeQuota: 125,
lockFreeQuota: false,
reserveFreeQuota: true
}),
beneficiary
)
{
_setDefaultRoyalty(royaltyReceiver, 1000);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/**
@dev Mint tokens purchased via the Seller.
*/
function _handlePurchase(
address to,
uint256 n,
bool
) internal override {
_safeMint(to, n);
}
/**
@dev Record of already-used signatures.
*/
mapping(bytes32 => bool) public usedMessages;
/**
@notice Mint tokens.
*/
function mintPublic(
address to,
bytes32 nonce,
bytes calldata sig
) external payable {
signers.requireValidSignature(
signaturePayload(to, nonce),
sig,
usedMessages
);
_purchase(to, 1);
}
function alreadyMinted(address to, bytes32 nonce)
external
view
returns (bool)
{
return
usedMessages[
SignatureChecker.generateMessage(signaturePayload(to, nonce))
];
}
/**
@dev Constructs the buffer that is hashed for validation with a minting
signature.
*/
function signaturePayload(address to, bytes32 nonce)
internal
pure
returns (bytes memory)
{
return abi.encodePacked(to, nonce);
}
/**
@dev Required override to select the correct baseTokenURI.
*/
function _baseURI()
internal
view
override(BaseTokenURI, ERC721A)
returns (string memory)
{
return BaseTokenURI._baseURI();
}
/**
@notice If set, contract to which tokenURI() calls are proxied.
*/
ITokenURIGenerator public renderingContract;
/**
@notice Sets the optional tokenURI override contract.
*/
function setRenderingContract(ITokenURIGenerator _contract)
external
onlyOwner
{
renderingContract = _contract;
}
/**
@notice If renderingContract is set then returns its tokenURI(tokenId)
return value, otherwise returns the standard baseTokenURI + tokenId.
*/
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
if (address(renderingContract) != address(0)) {
return renderingContract.tokenURI(tokenId);
}
return super.tokenURI(tokenId);
}
/**
@notice Sets the contract-wide royalty info.
*/
function setRoyaltyInfo(address receiver, uint96 feeBasisPoints)
external
onlyOwner
{
_setDefaultRoyalty(receiver, feeBasisPoints);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721ACommon, ERC2981, AccessControlEnumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
It compiles ok, but when I tried to create a test for minting, I must generate a valid signature...
This is the test
const { expect } = require('chai');
describe("TestBirds", function () {
it ("Should return correct name, URI, owner and beneficiary", async function () {
const [owner, addr1] = await hre.ethers.getSigners()
provider = ethers.provider
const TestBirdsContract = await hre.ethers.getContractFactory("TestBirds")
const testBirdsContractDeployed = await TestBirdsContract.deploy(
"TestBirds",
"APFP",
"https://test.url/",
owner.address,
owner.address)
console.log(await provider.getBalance(owner.address));
await testBirdsContractDeployed.deployed()
const nonce = await ethers.provider.getTransactionCount(owner.address, "latest")
await testBirdsContractDeployed.mintPublic(owner.address, nonce, signature???)
expect(await testBirdsContractDeployed.name()).to.equal("TestBirds")
expect(await testBirdsContractDeployed.tokenURI(0), "https://test.url/0")
expect(await testBirdsContractDeployed.ownerOf(0)).to.equal(owner.address)
})
})
How should I sing this in order to work? I can not test the contract without the sign. If I remove the signature param from the contract it works, but that is not what I want.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看来唯一缺少的是添加签名者。这似乎适用于您的测试合同...
It seems that the only missing was to add a signer. This seems to work for your test contract...
我已经尝试了以下内容,但尚未取得太大的成功:
这是针对以下合同的测试:
据我了解,签名的消息应与消息匹配,
ecdsa.toethsignedmessagehash(data)
将
\ x19ethereum签名的消息附加到消息的开始。匹配后,它可以恢复签名地址,但似乎还不错。
I've attempted the following, but without much success yet:
That is a test against the following contract:
From what I understood, the signed message should match the message, and the
ECDSA.toEthSignedMessageHash(data)
appends the
\x19Ethereum Signed Message:\n
to the beggining of the message. After it matches, it can recover the signer address, but it doesn't seem to work quite right yet.